~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

Small fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
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>
26
25
#include <drizzled/gettext.h>
27
26
#include <drizzled/util/convert.h>
28
27
#include <drizzled/error.h>
33
32
#include <drizzled/item/return_int.h>
34
33
#include <drizzled/item/empty_string.h>
35
34
#include <drizzled/item/return_date_time.h>
36
 
#include <drizzled/virtual_column_info.h>
37
35
#include <drizzled/sql_base.h>
38
36
#include <drizzled/db.h>
39
37
#include <drizzled/field/timestamp.h>
41
39
#include <drizzled/lock.h>
42
40
#include <drizzled/item/return_date_time.h>
43
41
#include <drizzled/item/empty_string.h>
 
42
#include "drizzled/plugin/registry.h"
 
43
#include <drizzled/plugin/info_schema_table.h>
 
44
#include <drizzled/message/schema.pb.h>
 
45
#include <drizzled/plugin/client.h>
 
46
#include <mysys/cached_directory.h>
 
47
#include <sys/stat.h>
44
48
 
45
49
#include <string>
46
50
#include <iostream>
47
51
#include <sstream>
 
52
#include <vector>
 
53
#include <algorithm>
48
54
 
49
55
using namespace std;
 
56
using namespace drizzled;
50
57
 
51
58
inline const char *
52
59
str_or_nil(const char *str)
54
61
  return str ? str : "<nil>";
55
62
}
56
63
 
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);
 
64
static void store_key_options(String *packet, Table *table, KEY *key_info);
62
65
 
63
66
 
64
67
 
72
75
      if (*wildstr == wild_prefix && wildstr[1])
73
76
        wildstr++;
74
77
      if (my_toupper(cs, *wildstr++) != my_toupper(cs, *str++))
75
 
        return(1);
 
78
        return (1);
76
79
    }
77
80
    if (! *wildstr )
78
81
      return (*str != 0);
83
86
    }
84
87
    else
85
88
    {                                           /* Found '*' */
86
 
      if (!*wildstr)
87
 
        return(0);              /* '*' as last char: OK */
 
89
      if (! *wildstr)
 
90
        return (0);             /* '*' as last char: OK */
88
91
      flag=(*wildstr != wild_many && *wildstr != wild_one);
89
92
      do
90
93
      {
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)
 
94
        if (flag)
 
95
        {
 
96
          char cmp;
 
97
          if ((cmp= *wildstr) == wild_prefix && wildstr[1])
 
98
            cmp= wildstr[1];
 
99
          cmp= my_toupper(cs, cmp);
 
100
          while (*str && my_toupper(cs, *str) != cmp)
 
101
            str++;
 
102
          if (! *str)
 
103
            return (1);
 
104
        }
 
105
        if (wild_case_compare(cs, str, wildstr) == 0)
 
106
          return (0);
 
107
      } while (*str++);
100
108
      return (1);
101
 
        }
102
 
  if (wild_case_compare(cs, str,wildstr) == 0)
103
 
      return (0);
104
 
      } while (*str++);
105
 
      return(1);
106
109
    }
107
110
  }
108
111
  return (*str != '\0');
109
112
}
110
113
 
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
 
  {
 
114
 
 
115
/**
 
116
 * @brief
 
117
 *   Find subdirectories (schemas) in a given directory (datadir).
 
118
 *
 
119
 * @param[in]  session    Thread Cursor
 
120
 * @param[out] files      Put found entries in this list
 
121
 * @param[in]  path       Path to database
 
122
 * @param[in]  wild       Filter for found entries
 
123
 *
 
124
 * @retval false   Success
 
125
 * @retval true    Error
 
126
 */
 
127
static bool find_schemas(Session *session, vector<LEX_STRING*> &files,
 
128
                         const char *path, const char *wild)
 
129
{
 
130
  if (wild && (wild[0] == '\0'))
 
131
    wild= 0;
 
132
 
 
133
  CachedDirectory directory(path);
 
134
 
 
135
  if (directory.fail())
 
136
  {
 
137
    my_errno= directory.getError();
 
138
    my_error(ER_CANT_READ_DIR, MYF(0), path, my_errno);
 
139
    return(true);
 
140
  }
 
141
 
 
142
  CachedDirectory::Entries entries= directory.getEntries();
 
143
  CachedDirectory::Entries::iterator entry_iter= entries.begin();
 
144
 
 
145
  while (entry_iter != entries.end())
 
146
  {
 
147
    uint32_t file_name_len;
261
148
    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
 
    }
 
149
    struct stat entry_stat;
 
150
    CachedDirectory::Entry *entry= *entry_iter;
 
151
 
 
152
    if ((entry->filename == ".") || (entry->filename == ".."))
 
153
    {
 
154
      ++entry_iter;
 
155
      continue;
 
156
    }
 
157
 
 
158
    if (stat(entry->filename.c_str(), &entry_stat))
 
159
    {
 
160
      my_errno= errno;
 
161
      my_error(ER_CANT_GET_STAT, MYF(0), entry->filename.c_str(), my_errno);
 
162
      return(true);
 
163
    }
 
164
 
 
165
    if (! S_ISDIR(entry_stat.st_mode))
 
166
    {
 
167
      ++entry_iter;
 
168
      continue;
 
169
    }
 
170
 
 
171
    file_name_len= filename_to_tablename(entry->filename.c_str(), uname,
 
172
                                         sizeof(uname));
 
173
    if (wild && wild_compare(uname, wild, 0))
 
174
    {
 
175
      ++entry_iter;
 
176
      continue;
 
177
    }
 
178
 
 
179
    LEX_STRING *file_name= 0;
 
180
    file_name= session->make_lex_string(file_name, uname, file_name_len, true);
 
181
    if (file_name == NULL)
 
182
      return(true);
 
183
 
 
184
    files.push_back(file_name);
 
185
    ++entry_iter;
324
186
  }
325
 
  my_dirend(dirp);
326
187
 
327
 
  return(FIND_FILES_OK);
 
188
  return(false);
328
189
}
329
190
 
330
191
 
331
 
bool
332
 
mysqld_show_create(Session *session, TableList *table_list)
 
192
bool drizzled_show_create(Session *session, TableList *table_list)
333
193
{
334
 
  Protocol *protocol= session->protocol;
335
194
  char buff[2048];
336
195
  String buffer(buff, sizeof(buff), system_charset_info);
337
196
 
338
197
  /* Only one table for now, but VIEW can involve several tables */
339
 
  if (open_normal_and_derived_tables(session, table_list, 0))
 
198
  if (session->openTables(table_list))
340
199
  {
341
200
    if (session->is_error())
342
 
      return(true);
 
201
      return true;
343
202
 
344
203
    /*
345
204
      Clear all messages with 'error' level status and
352
211
 
353
212
  buffer.length(0);
354
213
 
355
 
  if (store_create_info(session, table_list, &buffer, NULL))
356
 
    return(true);
 
214
  if (store_create_info(table_list, &buffer, NULL))
 
215
    return true;
357
216
 
358
217
  List<Item> field_list;
359
218
  {
360
219
    field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
361
220
    // 1024 is for not to confuse old clients
362
221
    field_list.push_back(new Item_empty_string("Create Table",
363
 
                                               cmax(buffer.length(),(uint32_t)1024)));
 
222
                                               max(buffer.length(),(uint32_t)1024)));
364
223
  }
365
224
 
366
 
  if (protocol->send_fields(&field_list,
367
 
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
368
 
    return(true);
369
 
  protocol->prepare_for_resend();
 
225
  if (session->client->sendFields(&field_list))
 
226
    return true;
370
227
  {
371
228
    if (table_list->schema_table)
372
 
      protocol->store(table_list->schema_table->table_name,
373
 
                      system_charset_info);
 
229
      session->client->store(table_list->schema_table->getTableName().c_str());
374
230
    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)
 
231
      session->client->store(table_list->table->alias);
 
232
  }
 
233
 
 
234
  session->client->store(buffer.ptr(), buffer.length());
 
235
 
 
236
  if (session->client->flush())
 
237
    return true;
 
238
 
 
239
  session->my_eof();
 
240
  return false;
 
241
}
 
242
 
 
243
/**
 
244
  Get a CREATE statement for a given database.
 
245
 
 
246
  The database is identified by its name, passed as @c dbname parameter.
 
247
  The name should be encoded using the system character set (UTF8 currently).
 
248
 
 
249
  Resulting statement is stored in the string pointed by @c buffer. The string
 
250
  is emptied first and its character set is set to the system character set.
 
251
 
 
252
  If HA_LEX_CREATE_IF_NOT_EXISTS flag is set in @c create_info->options, then
 
253
  the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
 
254
  in @c create_options are ignored.
 
255
 
 
256
  @param  session           The current thread instance.
 
257
  @param  dbname        The name of the database.
 
258
  @param  buffer        A String instance where the statement is stored.
 
259
  @param  create_info   If not NULL, the options member influences the resulting
 
260
                        CRATE statement.
 
261
 
 
262
  @returns true if errors are detected, false otherwise.
 
263
*/
 
264
 
 
265
static bool store_db_create_info(const char *dbname, String *buffer, bool if_not_exists)
 
266
{
 
267
  message::Schema schema;
 
268
 
 
269
  if (!my_strcasecmp(system_charset_info, dbname,
 
270
                     INFORMATION_SCHEMA_NAME.c_str()))
 
271
  {
 
272
    dbname= INFORMATION_SCHEMA_NAME.c_str();
 
273
  }
 
274
  else
 
275
  {
 
276
    int r= get_database_metadata(dbname, &schema);
 
277
    if(r < 0)
 
278
      return true;
 
279
  }
 
280
 
 
281
  buffer->length(0);
 
282
  buffer->free();
 
283
  buffer->set_charset(system_charset_info);
 
284
  buffer->append(STRING_WITH_LEN("CREATE DATABASE "));
 
285
 
 
286
  if (if_not_exists)
 
287
    buffer->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
288
 
 
289
  buffer->append_identifier(dbname, strlen(dbname));
 
290
 
 
291
  if (schema.has_collation() && strcmp(schema.collation().c_str(),
 
292
                                       default_charset_info->name))
 
293
  {
 
294
    buffer->append(" COLLATE = ");
 
295
    buffer->append(schema.collation().c_str());
 
296
  }
 
297
 
 
298
  return false;
 
299
}
 
300
 
 
301
bool mysqld_show_create_db(Session *session, char *dbname, bool if_not_exists)
389
302
{
390
303
  char buff[2048];
391
304
  String buffer(buff, sizeof(buff), system_charset_info);
392
 
  Protocol *protocol=session->protocol;
393
305
 
394
 
  if (store_db_create_info(session, dbname, &buffer, create_info))
 
306
  if (store_db_create_info(dbname, &buffer, if_not_exists))
395
307
  {
396
308
    /*
397
309
      This assumes that the only reason for which store_db_create_info()
398
310
      can fail is incorrect database name (which is the case now).
399
311
    */
400
312
    my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
401
 
    return(true);
 
313
    return true;
402
314
  }
403
315
 
404
316
  List<Item> field_list;
405
317
  field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
406
318
  field_list.push_back(new Item_empty_string("Create Database",1024));
407
319
 
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
 
 
 
320
  if (session->client->sendFields(&field_list))
 
321
    return true;
 
322
 
 
323
  session->client->store(dbname, strlen(dbname));
 
324
  session->client->store(buffer.ptr(), buffer.length());
 
325
 
 
326
  if (session->client->flush())
 
327
    return true;
 
328
  session->my_eof();
 
329
  return false;
 
330
}
457
331
 
458
332
/*
459
333
  Get the quote character for displaying an identifier.
460
334
 
461
335
  SYNOPSIS
462
336
    get_quote_char_for_identifier()
463
 
    session             Thread handler
464
 
    name        name to quote
465
 
    length      length of name
466
337
 
467
338
  IMPLEMENTATION
468
339
    Force quoting in the following cases:
478
349
    #     Quote character
479
350
*/
480
351
 
481
 
int get_quote_char_for_identifier(Session *, const char *, uint32_t)
 
352
int get_quote_char_for_identifier()
482
353
{
483
354
  return '`';
484
355
}
485
356
 
486
357
 
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
 
 
505
358
#define LIST_PROCESS_HOST_LEN 64
506
359
 
507
 
static bool get_field_default_value(Session *,
508
 
                                    Field *timestamp_field,
 
360
static bool get_field_default_value(Field *timestamp_field,
509
361
                                    Field *field, String *def_value,
510
362
                                    bool quoted)
511
363
{
521
373
 
522
374
  has_default= (field->type() != DRIZZLE_TYPE_BLOB &&
523
375
                !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
524
 
                field->unireg_check != Field::NEXT_NUMBER
525
 
                  && has_now_default);
 
376
                field->unireg_check != Field::NEXT_NUMBER);
526
377
 
527
378
  def_value->length(0);
528
379
  if (has_default)
552
403
    else if (field->maybe_null() && quoted)
553
404
      def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
554
405
    else
555
 
      return 0;
556
 
 
 
406
      return false;
557
407
  }
558
408
  return has_default;
559
409
}
563
413
 
564
414
  SYNOPSIS
565
415
    store_create_info()
566
 
    session               The thread
567
416
    table_list        A list containing one table to write statement
568
417
                      for.
569
418
    packet            Pointer to a string where statement will be
581
430
    0       OK
582
431
 */
583
432
 
584
 
int store_create_info(Session *session, TableList *table_list, String *packet,
585
 
                      HA_CREATE_INFO *create_info_arg)
 
433
int store_create_info(TableList *table_list, String *packet, HA_CREATE_INFO *create_info_arg)
586
434
{
587
435
  List<Item> field_list;
588
436
  char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
594
442
  uint32_t primary_key;
595
443
  KEY *key_info;
596
444
  Table *table= table_list->table;
597
 
  handler *file= table->file;
598
 
  TABLE_SHARE *share= table->s;
 
445
  Cursor *file= table->file;
 
446
  TableShare *share= table->s;
599
447
  HA_CREATE_INFO create_info;
600
448
  bool show_table_options= false;
601
449
  my_bitmap_map *old_map;
602
450
 
603
 
  restore_record(table, s->default_values); // Get empty record
 
451
  table->restoreRecordAsDefault(); // Get empty record
604
452
 
605
453
  if (share->tmp_table)
606
454
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
610
458
      (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
611
459
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
612
460
  if (table_list->schema_table)
613
 
    alias= table_list->schema_table->table_name;
 
461
    alias= table_list->schema_table->getTableName().c_str();
614
462
  else
615
 
  {
616
 
    if (lower_case_table_names == 2)
617
 
      alias= table->alias;
618
 
    else
619
 
    {
620
 
      alias= share->table_name.str;
621
 
    }
622
 
  }
 
463
    alias= share->table_name.str;
 
464
 
623
465
  packet->append_identifier(alias, strlen(alias));
624
466
  packet->append(STRING_WITH_LEN(" (\n"));
625
467
  /*
645
487
    else
646
488
      type.set_charset(system_charset_info);
647
489
 
648
 
    if (field->vcol_info)
649
 
    {
650
 
      packet->append(STRING_WITH_LEN("VIRTUAL "));
651
 
    }
652
 
 
653
490
    field->sql_type(type);
654
491
    packet->append(type.ptr(), type.length(), system_charset_info);
655
492
 
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
 
 
667
493
    if (field->has_charset())
668
494
    {
669
495
      if (field->charset() != share->table_charset)
670
496
      {
671
 
        packet->append(STRING_WITH_LEN(" CHARACTER SET "));
672
 
        packet->append(field->charset()->csname);
 
497
        packet->append(STRING_WITH_LEN(" CHARACTER SET "));
 
498
        packet->append(field->charset()->csname);
673
499
      }
 
500
 
674
501
      /*
675
 
        For string types dump collation name only if
676
 
        collation is not primary for the given charset
 
502
        For string types dump collation name only if
 
503
        collation is not primary for the given charset
677
504
      */
678
505
      if (!(field->charset()->state & MY_CS_PRIMARY))
679
506
      {
680
 
        packet->append(STRING_WITH_LEN(" COLLATE "));
681
 
        packet->append(field->charset()->name);
 
507
        packet->append(STRING_WITH_LEN(" COLLATE "));
 
508
        packet->append(field->charset()->name);
682
509
      }
683
510
    }
684
511
 
702
529
      if (column_format)
703
530
      {
704
531
        packet->append(STRING_WITH_LEN(" /*!"));
705
 
        packet->append(STRING_WITH_LEN(DRIZZLE_VERSION_TABLESPACE_IN_FRM_STR));
706
532
        packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
707
533
        if (column_format == COLUMN_FORMAT_TYPE_FIXED)
708
534
          packet->append(STRING_WITH_LEN(" FIXED */"));
710
536
          packet->append(STRING_WITH_LEN(" DYNAMIC */"));
711
537
      }
712
538
    }
713
 
    if (!field->vcol_info &&
714
 
        get_field_default_value(session, table->timestamp_field,
715
 
                                field, &def_value, 1))
 
539
    if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
716
540
    {
717
541
      packet->append(STRING_WITH_LEN(" DEFAULT "));
718
542
      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
770
594
 
771
595
      if (key_part->field)
772
596
        packet->append_identifier(key_part->field->field_name,
773
 
                          strlen(key_part->field->field_name));
 
597
                                  strlen(key_part->field->field_name));
774
598
      if (key_part->field &&
775
599
          (key_part->length !=
776
600
           table->field[key_part->fieldnr-1]->key_length()))
777
601
      {
778
 
        buff= "(";
779
 
        buff= to_string(buff, (int32_t) key_part->length /
780
 
                              key_part->field->charset()->mbmaxlen);
781
 
        buff += ")";
 
602
        buff.assign("(");
 
603
        buff.append(to_string((int32_t) key_part->length /
 
604
                              key_part->field->charset()->mbmaxlen));
 
605
        buff.append(")");
782
606
        packet->append(buff.c_str(), buff.length());
783
607
      }
784
608
    }
785
609
    packet->append(')');
786
 
    store_key_options(session, packet, table, key_info);
 
610
    store_key_options(packet, table, key_info);
787
611
  }
788
612
 
789
613
  /*
813
637
        (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
814
638
    {
815
639
      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());
 
640
      packet->append(file->engine->getName().c_str());
856
641
    }
857
642
 
858
643
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
859
644
      packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
860
645
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
861
646
      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"));
872
647
    if (create_info.row_type != ROW_TYPE_DEFAULT)
873
648
    {
874
649
      packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
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)
 
650
      packet->append(ha_row_type[(uint32_t) create_info.row_type]);
 
651
    }
 
652
    if (table->s->hasKeyBlockSize())
883
653
    {
884
654
      packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
885
 
      buff= to_string(table->s->key_block_size);
 
655
      buff= to_string(table->s->getKeyBlockSize());
886
656
      packet->append(buff.c_str(), buff.length());
887
657
    }
888
658
    if (share->block_size)
892
662
      packet->append(buff.c_str(), buff.length());
893
663
    }
894
664
    table->file->append_create_info(packet);
895
 
    if (share->comment.length)
 
665
    if (share->hasComment() && share->getCommentLength())
896
666
    {
897
667
      packet->append(STRING_WITH_LEN(" COMMENT="));
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);
 
668
      append_unescaped(packet, share->getComment(),
 
669
                       share->getCommentLength());
 
670
    }
907
671
  }
908
672
  table->restore_column_map(old_map);
909
673
  return(0);
910
674
}
911
675
 
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)
 
676
static void store_key_options(String *packet, Table *table, KEY *key_info)
970
677
{
971
678
  char *end, buff[32];
972
679
 
977
684
    packet->append(STRING_WITH_LEN(" USING HASH"));
978
685
 
979
686
  if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
980
 
      table->s->key_block_size != key_info->block_size)
 
687
      table->s->getKeyBlockSize() != key_info->block_size)
981
688
  {
982
689
    packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
983
690
    end= int64_t10_to_str(key_info->block_size, buff, 10);
984
 
    packet->append(buff, (uint) (end - buff));
 
691
    packet->append(buff, (uint32_t) (end - buff));
985
692
  }
986
693
 
987
694
  assert(test(key_info->flags & HA_USES_COMMENT) ==
1004
711
public:
1005
712
  static void *operator new(size_t size)
1006
713
  {
1007
 
    return (void*) sql_alloc((uint) size);
 
714
    return (void*) sql_alloc((uint32_t) size);
1008
715
  }
1009
716
  static void operator delete(void *, size_t)
1010
717
  { TRASH(ptr, size); }
1011
718
 
1012
 
  ulong thread_id;
 
719
  my_thread_id thread_id;
1013
720
  time_t start_time;
1014
721
  uint32_t   command;
1015
722
  const char *user,*host,*db,*proc_info,*state_info;
1020
727
template class I_List<thread_info>;
1021
728
#endif
1022
729
 
1023
 
void mysqld_list_processes(Session *session,const char *user, bool verbose)
 
730
void mysqld_list_processes(Session *session,const char *user, bool)
1024
731
{
1025
732
  Item *field;
1026
733
  List<Item> field_list;
1027
734
  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
735
 
1032
736
  field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS));
1033
737
  field_list.push_back(new Item_empty_string("User",16));
1034
738
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
1035
739
  field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN));
1036
 
  field->maybe_null=1;
 
740
  field->maybe_null= true;
1037
741
  field_list.push_back(new Item_empty_string("Command",16));
1038
742
  field_list.push_back(new Item_return_int("Time",7, DRIZZLE_TYPE_LONG));
1039
743
  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))
 
744
  field->maybe_null= true;
 
745
  field_list.push_back(field=new Item_empty_string("Info", PROCESS_LIST_WIDTH));
 
746
  field->maybe_null= true;
 
747
  if (session->client->sendFields(&field_list))
1045
748
    return;
1046
749
 
1047
750
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
1048
751
  if (!session->killed)
1049
752
  {
1050
 
    I_List_iterator<Session> it(threads);
1051
753
    Session *tmp;
1052
 
    while ((tmp=it++))
 
754
    for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
1053
755
    {
 
756
      tmp= *it;
1054
757
      Security_context *tmp_sctx= &tmp->security_ctx;
1055
758
      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))))
 
759
      if (tmp->client->isConnected() && (!user || (tmp_sctx->user.c_str() && !strcmp(tmp_sctx->user.c_str(), user))))
1057
760
      {
1058
761
        thread_info *session_info= new thread_info;
1059
762
 
1060
763
        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"));
 
764
        session_info->user= session->strdup(tmp_sctx->user.c_str() ? tmp_sctx->user.c_str() : "unauthenticated user");
1064
765
        session_info->host= session->strdup(tmp_sctx->ip.c_str());
1065
766
        if ((session_info->db=tmp->db))             // Safe test
1066
767
          session_info->db=session->strdup(session_info->db);
1067
768
        session_info->command=(int) tmp->command;
1068
769
        if ((mysys_var= tmp->mysys_var))
1069
770
          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") :
 
771
 
 
772
        if (tmp->killed == Session::KILL_CONNECTION)
 
773
          session_info->proc_info= (char*) "Killed";
 
774
        else
 
775
          session_info->proc_info= command_name[session_info->command].str;
 
776
 
 
777
        session_info->state_info= (char*) (tmp->client->isWriting() ?
 
778
                                           "Writing to net" :
 
779
                                           tmp->client->isReading() ?
 
780
                                           (session_info->command == COM_SLEEP ?
 
781
                                            NULL : "Reading from net") :
1076
782
                                       tmp->get_proc_info() ? tmp->get_proc_info() :
1077
783
                                       tmp->mysys_var &&
1078
784
                                       tmp->mysys_var->current_cond ?
1081
787
          pthread_mutex_unlock(&mysys_var->mutex);
1082
788
 
1083
789
        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
 
        }
 
790
        session_info->query= NULL;
 
791
        if (tmp->process_list_info[0])
 
792
          session_info->query= session->strdup(tmp->process_list_info);
1095
793
        thread_infos.append(session_info);
1096
794
      }
1097
795
    }
1102
800
  time_t now= time(NULL);
1103
801
  while ((session_info=thread_infos.get()))
1104
802
  {
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);
 
803
    session->client->store((uint64_t) session_info->thread_id);
 
804
    session->client->store(session_info->user);
 
805
    session->client->store(session_info->host);
 
806
    session->client->store(session_info->db);
 
807
    session->client->store(session_info->proc_info);
 
808
 
1114
809
    if (session_info->start_time)
1115
 
      protocol->store((uint32_t) (now - session_info->start_time));
 
810
      session->client->store((uint32_t) (now - session_info->start_time));
1116
811
    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 */
 
812
      session->client->store();
 
813
 
 
814
    session->client->store(session_info->state_info);
 
815
    session->client->store(session_info->query);
 
816
 
 
817
    if (session->client->flush())
 
818
      break;
1122
819
  }
1123
 
  my_eof(session);
 
820
  session->my_eof();
1124
821
  return;
1125
822
}
1126
823
 
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
 
 
1222
824
/*****************************************************************************
1223
825
  Status functions
1224
826
*****************************************************************************/
1225
827
 
1226
 
static DYNAMIC_ARRAY all_status_vars;
 
828
static vector<SHOW_VAR *> all_status_vars;
1227
829
static bool status_vars_inited= 0;
1228
830
static int show_var_cmp(const void *var1, const void *var2)
1229
831
{
1230
832
  return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
1231
833
}
1232
834
 
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);
 
835
class show_var_cmp_functor
 
836
{
 
837
  public:
 
838
  show_var_cmp_functor() { }
 
839
  inline bool operator()(const SHOW_VAR *var1, const SHOW_VAR *var2) const
 
840
  {
 
841
    int val= strcmp(var1->name, var2->name);
 
842
    return (val < 0);
 
843
  }
 
844
};
 
845
 
 
846
class show_var_remove_if
 
847
{
 
848
  public:
 
849
  show_var_remove_if() { }
 
850
  inline bool operator()(const SHOW_VAR *curr) const
 
851
  {
 
852
    return (curr->type == SHOW_UNDEF);
 
853
  }
 
854
};
 
855
 
 
856
SHOW_VAR *getFrontOfStatusVars()
 
857
{
 
858
  return all_status_vars.front();
1252
859
}
1253
860
 
1254
861
/*
1267
874
    As a special optimization, if add_status_vars() is called before
1268
875
    init_status_vars(), it assumes "startup mode" - neither concurrent access
1269
876
    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}
1272
877
*/
1273
878
int add_status_vars(SHOW_VAR *list)
1274
879
{
1275
880
  int res= 0;
1276
881
  if (status_vars_inited)
1277
882
    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
 
  }
1284
883
  while (list->name)
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
 
884
    all_status_vars.insert(all_status_vars.begin(), list++);
1288
885
  if (status_vars_inited)
1289
 
    sort_dynamic(&all_status_vars, show_var_cmp);
1290
 
err:
 
886
    sort(all_status_vars.begin(), all_status_vars.end(),
 
887
         show_var_cmp_functor());
1291
888
  if (status_vars_inited)
1292
889
    pthread_mutex_unlock(&LOCK_status);
1293
890
  return res;
1303
900
*/
1304
901
void init_status_vars()
1305
902
{
1306
 
  status_vars_inited=1;
1307
 
  sort_dynamic(&all_status_vars, show_var_cmp);
 
903
  status_vars_inited= 1;
 
904
  sort(all_status_vars.begin(), all_status_vars.end(),
 
905
       show_var_cmp_functor());
1308
906
}
1309
907
 
1310
908
void reset_status_vars()
1311
909
{
1312
 
  SHOW_VAR *ptr= (SHOW_VAR*) all_status_vars.buffer;
1313
 
  SHOW_VAR *last= ptr + all_status_vars.elements;
1314
 
  for (; ptr < last; ptr++)
 
910
  vector<SHOW_VAR *>::iterator p= all_status_vars.begin();
 
911
  while (p != all_status_vars.end())
1315
912
  {
1316
913
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
1317
 
    if (ptr->type == SHOW_LONG)
1318
 
      *(ulong*) ptr->value= 0;
 
914
    if ((*p)->type == SHOW_LONG)
 
915
      (*p)->value= 0;
 
916
    ++p;
1319
917
  }
1320
918
}
1321
919
 
1325
923
  DESCRIPTION
1326
924
    This function is not strictly required if all add_to_status/
1327
925
    remove_status_vars are properly paired, but it's a safety measure that
1328
 
    deletes everything from the all_status_vars[] even if some
 
926
    deletes everything from the all_status_vars vector even if some
1329
927
    remove_status_vars were forgotten
1330
928
*/
1331
929
void free_status_vars()
1332
930
{
1333
 
  delete_dynamic(&all_status_vars);
 
931
  all_status_vars.clear();
1334
932
}
1335
933
 
1336
934
/*
1352
950
  if (status_vars_inited)
1353
951
  {
1354
952
    pthread_mutex_lock(&LOCK_status);
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;
 
953
    SHOW_VAR *all= all_status_vars.front();
 
954
    int a= 0, b= all_status_vars.size(), c= (a+b)/2;
1357
955
 
1358
956
    for (; list->name; list++)
1359
957
    {
1360
958
      int res= 0;
1361
 
      for (a= 0, b= all_status_vars.elements; b-a > 1; c= (a+b)/2)
 
959
      for (a= 0, b= all_status_vars.size(); b-a > 1; c= (a+b)/2)
1362
960
      {
1363
961
        res= show_var_cmp(list, all+c);
1364
962
        if (res < 0)
1371
969
      if (res == 0)
1372
970
        all[c].type= SHOW_UNDEF;
1373
971
    }
1374
 
    shrink_var_array(&all_status_vars);
 
972
    /* removes all the SHOW_UNDEF elements from the vector */
 
973
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
974
                            all_status_vars.end(),show_var_remove_if()),
 
975
                            all_status_vars.end());
1375
976
    pthread_mutex_unlock(&LOCK_status);
1376
977
  }
1377
978
  else
1378
979
  {
1379
 
    SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
 
980
    SHOW_VAR *all= all_status_vars.front();
1380
981
    uint32_t i;
1381
982
    for (; list->name; list++)
1382
983
    {
1383
 
      for (i= 0; i < all_status_vars.elements; i++)
 
984
      for (i= 0; i < all_status_vars.size(); i++)
1384
985
      {
1385
986
        if (show_var_cmp(list, all+i))
1386
987
          continue;
1388
989
        break;
1389
990
      }
1390
991
    }
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
 
 
 
992
    /* removes all the SHOW_UNDEF elements from the vector */
 
993
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
994
                            all_status_vars.end(),show_var_remove_if()),
 
995
                            all_status_vars.end());
 
996
  }
 
997
}
1564
998
 
1565
999
/* collect status for all running threads */
1566
1000
 
1567
1001
void calc_sum_of_all_status(STATUS_VAR *to)
1568
1002
{
1569
 
 
1570
1003
  /* Ensure that thread id not killed during loop */
1571
1004
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
1572
1005
 
1573
 
  I_List_iterator<Session> it(threads);
1574
 
  Session *tmp;
1575
 
 
1576
1006
  /* Get global values as base */
1577
1007
  *to= global_status_var;
1578
1008
 
1579
1009
  /* Add to this status from existing threads */
1580
 
  while ((tmp= it++))
1581
 
    add_to_status(to, &tmp->status_var);
 
1010
  for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
 
1011
  {
 
1012
    add_to_status(to, &((*it)->status_var));
 
1013
  }
1582
1014
 
1583
1015
  pthread_mutex_unlock(&LOCK_thread_count);
1584
1016
  return;
1585
1017
}
1586
1018
 
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
1019
/*
1599
1020
  Store record to I_S table, convert HEAP table
1600
1021
  to MyISAM if necessary
1601
1022
 
1602
1023
  SYNOPSIS
1603
1024
    schema_table_store_record()
1604
 
    session                   thread handler
 
1025
    session                   thread Cursor
1605
1026
    table                 Information schema table to be updated
1606
1027
 
1607
1028
  RETURN
1614
1035
  int error;
1615
1036
  if ((error= table->file->ha_write_row(table->record[0])))
1616
1037
  {
1617
 
    TMP_TABLE_PARAM *param= table->pos_in_table_list->schema_table_param;
 
1038
    Tmp_Table_Param *param= table->pos_in_table_list->schema_table_param;
1618
1039
 
1619
1040
    if (create_myisam_from_heap(session, table, param->start_recinfo,
1620
1041
                                &param->recinfo, error, 0))
1621
 
      return 1;
 
1042
      return true;
1622
1043
  }
1623
 
  return 0;
 
1044
  return false;
1624
1045
}
1625
1046
 
1626
1047
 
1627
 
int make_table_list(Session *session, SELECT_LEX *sel,
1628
 
                    LEX_STRING *db_name, LEX_STRING *table_name)
 
1048
static int make_table_list(Session *session, Select_Lex *sel,
 
1049
                           LEX_STRING *db_name, LEX_STRING *table_name)
1629
1050
{
1630
1051
  Table_ident *table_ident;
1631
 
  table_ident= new Table_ident(session, *db_name, *table_name, 1);
 
1052
  table_ident= new Table_ident(*db_name, *table_name);
1632
1053
  sel->init_query();
1633
 
  if (!sel->add_table_to_list(session, table_ident, 0, 0, TL_READ))
 
1054
  if (! sel->add_table_to_list(session, table_ident, 0, 0, TL_READ))
1634
1055
    return 1;
1635
1056
  return 0;
1636
1057
}
1644
1065
           fill appropriate lookup_field_vals struct field
1645
1066
           with this value.
1646
1067
 
1647
 
  @param[in]      session                   thread handler
 
1068
  @param[in]      session                   thread Cursor
1648
1069
  @param[in]      item_func             part of WHERE condition
1649
1070
  @param[in]      table                 I_S table
1650
1071
  @param[in, out] lookup_field_vals     Struct which holds lookup values
1654
1075
    1             error, there can be no matching records for the condition
1655
1076
*/
1656
1077
 
1657
 
bool get_lookup_value(Session *session, Item_func *item_func,
1658
 
                      TableList *table,
1659
 
                      LOOKUP_FIELD_VALUES *lookup_field_vals)
 
1078
static bool get_lookup_value(Session *session, Item_func *item_func,
 
1079
                             TableList *table,
 
1080
                             LOOKUP_FIELD_VALUES *lookup_field_vals)
1660
1081
{
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 : "";
 
1082
  plugin::InfoSchemaTable *schema_table= table->schema_table;
 
1083
  const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
 
1084
    schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
 
1085
  const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
 
1086
    schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
1667
1087
 
1668
1088
  if (item_func->functype() == Item_func::EQ_FUNC ||
1669
1089
      item_func->functype() == Item_func::EQUAL_FUNC)
1727
1147
           from 'WHERE' condition if it's possible and
1728
1148
           fill lookup_field_vals struct fields with these values.
1729
1149
 
1730
 
  @param[in]      session                   thread handler
 
1150
  @param[in]      session                   thread Cursor
1731
1151
  @param[in]      cond                  WHERE condition
1732
1152
  @param[in]      table                 I_S table
1733
1153
  @param[in, out] lookup_field_vals     Struct which holds lookup values
1772
1192
}
1773
1193
 
1774
1194
 
1775
 
bool uses_only_table_name_fields(Item *item, TableList *table)
 
1195
static bool uses_only_table_name_fields(Item *item, TableList *table)
1776
1196
{
1777
1197
  if (item->type() == Item::FUNC_ITEM)
1778
1198
  {
1787
1207
  {
1788
1208
    Item_field *item_field= (Item_field*)item;
1789
1209
    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 : "";
 
1210
    plugin::InfoSchemaTable *schema_table= table->schema_table;
 
1211
    const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
 
1212
      schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
 
1213
    const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
 
1214
      schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
1796
1215
    if (table->table != item_field->field->table ||
1797
1216
        (cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
1798
1217
                               (unsigned char *) item_field->field_name,
1876
1295
           from LEX struct and fill lookup_field_vals struct field
1877
1296
           with these values.
1878
1297
 
1879
 
  @param[in]      session                   thread handler
 
1298
  @param[in]      session                   thread Cursor
1880
1299
  @param[in]      cond                  WHERE condition
1881
1300
  @param[in]      tables                I_S table
1882
1301
  @param[in, out] lookup_field_values   Struct which holds lookup values
1922
1341
}
1923
1342
 
1924
1343
 
1925
 
enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
 
1344
/**
 
1345
 * Function used for sorting with std::sort within make_db_list.
 
1346
 *
 
1347
 * @returns true if a < b, false otherwise
 
1348
 */
 
1349
 
 
1350
static bool lex_string_sort(const LEX_STRING *a, const LEX_STRING *b)
1926
1351
{
1927
 
  return (enum enum_schema_tables) (schema_table - &schema_tables[0]);
 
1352
  return (strcmp(a->str, b->str) < 0);
1928
1353
}
1929
1354
 
1930
1355
 
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,
 
1356
/**
 
1357
 * @brief
 
1358
 *   Create db names list. Information schema name always is first in list
 
1359
 *
 
1360
 * @param[in]  session          Thread Cursor
 
1361
 * @param[out] files            List of db names
 
1362
 * @param[in]  wild             Wild string
 
1363
 * @param[in]  idx_field_vals   idx_field_vals->db_name contains db name or
 
1364
 *                              wild string
 
1365
 * @param[out] with_i_schema    Returns 1 if we added 'IS' name to list
 
1366
 *                              otherwise returns 0
 
1367
 *
 
1368
 * @retval 0   Success
 
1369
 * @retval 1   Error
 
1370
 */
 
1371
int make_db_list(Session *session, vector<LEX_STRING*> &files,
1950
1372
                 LOOKUP_FIELD_VALUES *lookup_field_vals,
1951
1373
                 bool *with_i_schema)
1952
1374
{
1968
1390
                           lookup_field_vals->db_value.str))
1969
1391
    {
1970
1392
      *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);
 
1393
      files.push_back(i_s_name_copy);
 
1394
    }
 
1395
 
 
1396
    if (find_schemas(session, files, drizzle_data_home,
 
1397
                     lookup_field_vals->db_value.str) == true)
 
1398
    {
 
1399
      return 1;
 
1400
    }
 
1401
 
 
1402
    sort(files.begin()+1, files.end(), lex_string_sort);
 
1403
    return 0;
1976
1404
  }
1977
1405
 
1978
1406
 
1986
1414
                       lookup_field_vals->db_value.str))
1987
1415
    {
1988
1416
      *with_i_schema= 1;
1989
 
      if (files->push_back(i_s_name_copy))
1990
 
        return 1;
 
1417
      files.push_back(i_s_name_copy);
1991
1418
      return 0;
1992
1419
    }
1993
 
    if (files->push_back(&lookup_field_vals->db_value))
1994
 
      return 1;
 
1420
 
 
1421
    files.push_back(&lookup_field_vals->db_value);
1995
1422
    return 0;
1996
1423
  }
1997
1424
 
1999
1426
    Create list of existing databases. It is used in case
2000
1427
    of select from information schema table
2001
1428
  */
2002
 
  if (files->push_back(i_s_name_copy))
2003
 
    return 1;
 
1429
  files.push_back(i_s_name_copy);
 
1430
 
2004
1431
  *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);
 
1432
 
 
1433
  if (find_schemas(session, files, drizzle_data_home, NULL) == true)
 
1434
  {
 
1435
    return 1;
 
1436
  }
 
1437
 
 
1438
  sort(files.begin()+1, files.end(), lex_string_sort);
 
1439
  return 0;
2087
1440
}
2088
1441
 
2089
1442
 
2093
1446
  @details        The function creates the list of table names in
2094
1447
                  database
2095
1448
 
2096
 
  @param[in]      session                   thread handler
 
1449
  @param[in]      session                   thread Cursor
2097
1450
  @param[in]      table_names           List of table names in database
2098
1451
  @param[in]      lex                   pointer to LEX struct
2099
1452
  @param[in]      lookup_field_vals     pointer to LOOKUP_FIELD_VALUE struct
2107
1460
*/
2108
1461
 
2109
1462
static int
2110
 
make_table_name_list(Session *session, List<LEX_STRING> *table_names, LEX *lex,
 
1463
make_table_name_list(Session *session, vector<LEX_STRING*> &table_names, LEX *lex,
2111
1464
                     LOOKUP_FIELD_VALUES *lookup_field_vals,
2112
1465
                     bool with_i_schema, LEX_STRING *db_name)
2113
1466
{
2114
1467
  char path[FN_REFLEN];
2115
 
  build_table_filename(path, sizeof(path), db_name->str, "", "", 0);
 
1468
 
 
1469
  build_table_filename(path, sizeof(path), db_name->str, "", false);
2116
1470
  if (!lookup_field_vals->wild_table_value &&
2117
1471
      lookup_field_vals->table_value.str)
2118
1472
  {
2119
1473
    if (with_i_schema)
2120
1474
    {
2121
 
      if (find_schema_table(session, lookup_field_vals->table_value.str))
 
1475
      if (plugin::InfoSchemaTable::getTable(lookup_field_vals->table_value.str))
2122
1476
      {
2123
 
        if (table_names->push_back(&lookup_field_vals->table_value))
2124
 
          return 1;
 
1477
        table_names.push_back(&lookup_field_vals->table_value);
2125
1478
      }
2126
1479
    }
2127
1480
    else
2128
1481
    {
2129
 
      if (table_names->push_back(&lookup_field_vals->table_value))
2130
 
        return 1;
 
1482
      table_names.push_back(&lookup_field_vals->table_value);
2131
1483
    }
2132
1484
    return 0;
2133
1485
  }
2137
1489
    to the list
2138
1490
  */
2139
1491
  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)
 
1492
    return plugin::InfoSchemaTable::addTableToList(session, table_names,
 
1493
                                      lookup_field_vals->table_value.str);
 
1494
 
 
1495
  string db(db_name->str);
 
1496
 
 
1497
  plugin::TableNameIterator tniter(db);
 
1498
  int err= 0;
 
1499
  string table_name;
 
1500
 
 
1501
  do {
 
1502
    err= tniter.next(&table_name);
 
1503
 
 
1504
    if (err == 0)
2154
1505
    {
2155
 
      if (lex->sql_command != SQLCOM_SELECT)
2156
 
        return 1;
2157
 
      session->clear_error();
2158
 
      return 2;
 
1506
      LEX_STRING *file_name= NULL;
 
1507
      file_name= session->make_lex_string(file_name, table_name.c_str(),
 
1508
                                          table_name.length(), true);
 
1509
      const char* wild= lookup_field_vals->table_value.str;
 
1510
      if (wild && wild_compare(table_name.c_str(), wild, 0))
 
1511
        continue;
 
1512
      table_names.push_back(file_name);
2159
1513
    }
2160
 
    return 1;
 
1514
 
 
1515
  } while (err == 0);
 
1516
 
 
1517
  if (err > 0)
 
1518
  {
 
1519
    /* who knows what this error condition really does...
 
1520
       anyway, we're keeping behaviour from days of yore */
 
1521
    if (lex->sql_command != SQLCOM_SELECT)
 
1522
      return 1;
 
1523
    session->clear_error();
 
1524
    return 2;
2161
1525
  }
 
1526
 
2162
1527
  return 0;
2163
1528
}
2164
1529
 
2166
1531
/**
2167
1532
  @brief          Fill I_S table for SHOW COLUMNS|INDEX commands
2168
1533
 
2169
 
  @param[in]      session                      thread handler
 
1534
  @param[in]      session                      thread Cursor
2170
1535
  @param[in]      tables                   TableList for I_S table
2171
1536
  @param[in]      schema_table             pointer to I_S structure
2172
1537
  @param[in]      open_tables_state_backup pointer to Open_tables_state object
2181
1546
 
2182
1547
static int
2183
1548
fill_schema_show_cols_or_idxs(Session *session, TableList *tables,
2184
 
                              ST_SCHEMA_TABLE *schema_table,
 
1549
                              plugin::InfoSchemaTable *schema_table,
2185
1550
                              Open_tables_state *open_tables_state_backup)
2186
1551
{
2187
1552
  LEX *lex= session->lex;
2208
1573
    SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
2209
1574
  */
2210
1575
  lex->sql_command= SQLCOM_SHOW_FIELDS;
2211
 
  res= open_normal_and_derived_tables(session, show_table_list,
2212
 
                                      DRIZZLE_LOCK_IGNORE_FLUSH);
 
1576
  res= session->openTables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
2213
1577
  lex->sql_command= save_sql_command;
2214
1578
  /*
2215
1579
    get_all_tables() returns 1 on failure and 0 on success thus
2228
1592
                                 show_table_list->db_length, false);
2229
1593
 
2230
1594
 
2231
 
   error= test(schema_table->process_table(session, show_table_list,
2232
 
                                           table, res, db_name,
2233
 
                                           table_name));
 
1595
   table->setWriteSet();
 
1596
   error= test(schema_table->processTable(session, show_table_list,
 
1597
                                          table, res, db_name,
 
1598
                                          table_name));
2234
1599
   session->temporary_tables= 0;
2235
 
   close_tables_for_reopen(session, &show_table_list);
 
1600
   session->close_tables_for_reopen(&show_table_list);
 
1601
 
2236
1602
   return(error);
2237
1603
}
2238
1604
 
2240
1606
/**
2241
1607
  @brief          Fill I_S table for SHOW Table NAMES commands
2242
1608
 
2243
 
  @param[in]      session                      thread handler
 
1609
  @param[in]      session                      thread Cursor
2244
1610
  @param[in]      table                    Table struct for I_S table
2245
1611
  @param[in]      db_name                  database name
2246
1612
  @param[in]      table_name               table name
2264
1630
  {
2265
1631
    char path[FN_REFLEN];
2266
1632
    (void) build_table_filename(path, sizeof(path), db_name->str,
2267
 
                                table_name->str, reg_ext, 0);
 
1633
                                table_name->str, false);
2268
1634
 
2269
1635
      table->field[3]->store(STRING_WITH_LEN("BASE Table"),
2270
1636
                             system_charset_info);
2291
1657
                  OPEN_FULL_TABLE - open FRM, data, index files
2292
1658
  @param[in]      tables               I_S table table_list
2293
1659
  @param[in]      schema_table         I_S table struct
2294
 
  @param[in]      schema_table_idx     I_S table index
2295
1660
 
2296
1661
  @return         return a set of flags
2297
1662
    @retval       SKIP_OPEN_TABLE | OPEN_FRM_ONLY | OPEN_FULL_TABLE
2298
1663
*/
2299
1664
 
2300
1665
static uint32_t get_table_open_method(TableList *tables,
2301
 
                                      ST_SCHEMA_TABLE *schema_table,
2302
 
                                      enum enum_schema_tables)
 
1666
                                      plugin::InfoSchemaTable *schema_table)
2303
1667
{
2304
1668
  /*
2305
1669
    determine which method will be used for table opening
2306
1670
  */
2307
 
  if (schema_table->i_s_requested_object & OPTIMIZE_I_S_TABLE)
 
1671
  if (schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
2308
1672
  {
2309
1673
    Field **ptr, *field;
2310
1674
    int table_open_method= 0, field_indx= 0;
2311
 
    for (ptr=tables->table->field; (field= *ptr) ; ptr++)
 
1675
    for (ptr= tables->table->field; (field= *ptr) ; ptr++)
2312
1676
    {
2313
 
      if (bitmap_is_set(tables->table->read_set, field->field_index))
2314
 
        table_open_method|= schema_table->fields_info[field_indx].open_method;
 
1677
      if (field->isReadSet())
 
1678
        table_open_method|= schema_table->getColumnOpenMethod(field_indx);
2315
1679
      field_indx++;
2316
1680
    }
2317
1681
    return table_open_method;
2318
1682
  }
2319
1683
  /* I_S tables which use get_all_tables but can not be optimized */
2320
 
  return (uint) OPEN_FULL_TABLE;
 
1684
  return (uint32_t) OPEN_FULL_TABLE;
2321
1685
}
2322
1686
 
2323
1687
 
2324
1688
/**
2325
1689
  @brief          Fill I_S table with data from FRM file only
2326
1690
 
2327
 
  @param[in]      session                      thread handler
 
1691
  @param[in]      session                      thread Cursor
2328
1692
  @param[in]      table                    Table struct for I_S table
2329
1693
  @param[in]      schema_table             I_S table struct
2330
1694
  @param[in]      db_name                  database name
2331
1695
  @param[in]      table_name               table name
2332
 
  @param[in]      schema_table_idx         I_S table index
2333
1696
 
2334
1697
  @return         Operation status
2335
1698
    @retval       0           Table is processed and we can continue
2339
1702
*/
2340
1703
 
2341
1704
static int fill_schema_table_from_frm(Session *session,TableList *tables,
2342
 
                                      ST_SCHEMA_TABLE *schema_table,
 
1705
                                      plugin::InfoSchemaTable *schema_table,
2343
1706
                                      LEX_STRING *db_name,
2344
 
                                      LEX_STRING *table_name,
2345
 
                                      enum enum_schema_tables)
 
1707
                                      LEX_STRING *table_name)
2346
1708
{
2347
1709
  Table *table= tables->table;
2348
 
  TABLE_SHARE *share;
 
1710
  TableShare *share;
2349
1711
  Table tbl;
2350
1712
  TableList table_list;
2351
1713
  uint32_t res= 0;
2353
1715
  char key[MAX_DBKEY_LENGTH];
2354
1716
  uint32_t key_length;
2355
1717
 
2356
 
  memset(&table_list, 0, sizeof(TableList));
2357
1718
  memset(&tbl, 0, sizeof(Table));
2358
1719
 
2359
1720
  table_list.table_name= table_name->str;
2360
1721
  table_list.db= db_name->str;
2361
1722
 
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);
 
1723
  key_length= table_list.create_table_def_key(key);
 
1724
  pthread_mutex_lock(&LOCK_open); /* Locking to get table share when filling schema table from FRM */
 
1725
  share= TableShare::getShare(session, &table_list, key, key_length, 0, &error);
2366
1726
  if (!share)
2367
1727
  {
2368
1728
    res= 0;
2372
1732
  {
2373
1733
    tbl.s= share;
2374
1734
    table_list.table= &tbl;
2375
 
    res= schema_table->process_table(session, &table_list, table,
2376
 
                                     res, db_name, table_name);
 
1735
    res= schema_table->processTable(session, &table_list, table,
 
1736
                                    res, db_name, table_name);
2377
1737
  }
 
1738
  /* For the moment we just set everything to read */
 
1739
  table->setReadSet();
2378
1740
 
2379
 
  release_table_share(share, RELEASE_NORMAL);
 
1741
  TableShare::release(share);
2380
1742
 
2381
1743
err:
2382
1744
  pthread_mutex_unlock(&LOCK_open);
2394
1756
                  temporary tables that are filled at query execution time.
2395
1757
                  Those I_S tables whose data are retrieved
2396
1758
                  from frm files and storage engine are filled by the function
2397
 
                  get_all_tables().
 
1759
                  plugin::InfoSchemaMethods::fillTable().
2398
1760
 
2399
 
  @param[in]      session                      thread handler
 
1761
  @param[in]      session                      thread Cursor
2400
1762
  @param[in]      tables                   I_S table
2401
1763
  @param[in]      cond                     'WHERE' condition
2402
1764
 
2404
1766
    @retval       0                        success
2405
1767
    @retval       1                        error
2406
1768
*/
2407
 
 
2408
 
int get_all_tables(Session *session, TableList *tables, COND *cond)
 
1769
int plugin::InfoSchemaMethods::fillTable(Session *session, TableList *tables, COND *cond)
2409
1770
{
2410
1771
  LEX *lex= session->lex;
2411
1772
  Table *table= tables->table;
2412
 
  SELECT_LEX *old_all_select_lex= lex->all_selects_list;
 
1773
  Select_Lex *old_all_select_lex= lex->all_selects_list;
2413
1774
  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;
 
1775
  Select_Lex *lsel= tables->schema_select_lex;
 
1776
  plugin::InfoSchemaTable *schema_table= tables->schema_table;
 
1777
  Select_Lex sel;
2417
1778
  LOOKUP_FIELD_VALUES lookup_field_vals;
2418
 
  LEX_STRING *db_name, *table_name;
2419
1779
  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);
 
1780
  vector<LEX_STRING*> db_names, table_names;
2423
1781
  COND *partial_cond= 0;
2424
1782
  uint32_t derived_tables= lex->derived_tables;
2425
1783
  int error= 1;
2435
1793
  */
2436
1794
  session->reset_n_backup_open_tables_state(&open_tables_state_backup);
2437
1795
 
2438
 
  schema_table_idx= get_schema_table_idx(schema_table);
2439
1796
  tables->table_open_method= table_open_method=
2440
 
    get_table_open_method(tables, schema_table, schema_table_idx);
 
1797
    get_table_open_method(tables, schema_table);
2441
1798
  /*
2442
1799
    this branch processes SHOW FIELDS, SHOW INDEXES commands.
2443
1800
    see sql_parse.cc, prepare_schema_table() function where
2473
1830
  if (lookup_field_vals.db_value.length &&
2474
1831
      !lookup_field_vals.wild_db_value)
2475
1832
    tables->has_db_lookup_value= true;
 
1833
 
2476
1834
  if (lookup_field_vals.table_value.length &&
2477
1835
      !lookup_field_vals.wild_table_value)
2478
1836
    tables->has_table_lookup_value= true;
2489
1847
    goto err;
2490
1848
  }
2491
1849
 
2492
 
  if (make_db_list(session, &db_names, &lookup_field_vals, &with_i_schema))
 
1850
  table->setWriteSet();
 
1851
  if (make_db_list(session, db_names, &lookup_field_vals, &with_i_schema))
2493
1852
    goto err;
2494
 
  it.rewind(); /* To get access to new elements in basis list */
2495
 
  while ((db_name= it++))
 
1853
 
 
1854
  for (vector<LEX_STRING*>::iterator db_name= db_names.begin(); db_name != db_names.end(); ++db_name )
2496
1855
  {
 
1856
    session->no_warnings_for_error= 1;
 
1857
    table_names.clear();
 
1858
    int res= make_table_name_list(session, table_names, lex,
 
1859
                                  &lookup_field_vals,
 
1860
                                  with_i_schema, *db_name);
 
1861
 
 
1862
    if (res == 2)   /* Not fatal error, continue */
 
1863
      continue;
 
1864
 
 
1865
    if (res)
 
1866
      goto err;
 
1867
 
 
1868
    
 
1869
    for (vector<LEX_STRING*>::iterator table_name= table_names.begin(); table_name != table_names.end(); ++table_name)
2497
1870
    {
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;
 
1871
      table->restoreRecordAsDefault();
 
1872
      table->field[schema_table->getFirstColumnIndex()]->
 
1873
        store((*db_name)->str, (*db_name)->length, system_charset_info);
 
1874
      table->field[schema_table->getSecondColumnIndex()]->
 
1875
        store((*table_name)->str, (*table_name)->length, system_charset_info);
2507
1876
 
2508
 
      List_iterator_fast<LEX_STRING> it_files(table_names);
2509
 
      while ((table_name= it_files++))
 
1877
      if (!partial_cond || partial_cond->val_int())
2510
1878
      {
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);
 
1879
        /*
 
1880
          If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN)
 
1881
          we can skip table opening and we don't have lookup value for
 
1882
          table name or lookup value is wild string(table name list is
 
1883
          already created by make_table_name_list() function).
 
1884
        */
 
1885
        if (! table_open_method &&
 
1886
            schema_table->getTableName().compare("TABLES") == 0 &&
 
1887
            (! lookup_field_vals.table_value.length ||
 
1888
             lookup_field_vals.wild_table_value))
 
1889
        {
 
1890
          if (schema_table_store_record(session, table))
 
1891
            goto err;      /* Out of space in temporary table */
 
1892
          continue;
 
1893
        }
2516
1894
 
2517
 
        if (!partial_cond || partial_cond->val_int())
 
1895
        /* SHOW Table NAMES command */
 
1896
        if (schema_table->getTableName().compare("TABLE_NAMES") == 0)
2518
1897
        {
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 */
 
1898
          if (fill_schema_table_names(session, tables->table, *db_name,
 
1899
                                      *table_name, with_i_schema))
2531
1900
            continue;
2532
 
          }
2533
 
 
2534
 
          /* SHOW Table NAMES command */
2535
 
          if (schema_table_idx == SCH_TABLE_NAMES)
 
1901
        }
 
1902
        else
 
1903
        {
 
1904
          if (!(table_open_method & ~OPEN_FRM_ONLY) &&
 
1905
              !with_i_schema)
2536
1906
          {
2537
 
            if (fill_schema_table_names(session, tables->table, db_name,
2538
 
                                        table_name, with_i_schema))
 
1907
            if (!fill_schema_table_from_frm(session, tables, schema_table, *db_name,
 
1908
                                            *table_name))
2539
1909
              continue;
2540
1910
          }
 
1911
 
 
1912
          LEX_STRING tmp_lex_string, orig_db_name;
 
1913
          /*
 
1914
            Set the parent lex of 'sel' because it is needed by
 
1915
            sel.init_query() which is called inside make_table_list.
 
1916
          */
 
1917
          session->no_warnings_for_error= 1;
 
1918
          sel.parent_lex= lex;
 
1919
          /* db_name can be changed in make_table_list() func */
 
1920
          if (!session->make_lex_string(&orig_db_name, (*db_name)->str,
 
1921
                                        (*db_name)->length, false))
 
1922
            goto err;
 
1923
 
 
1924
          if (make_table_list(session, &sel, *db_name, *table_name))
 
1925
            goto err;
 
1926
 
 
1927
          TableList *show_table_list= (TableList*) sel.table_list.first;
 
1928
          lex->all_selects_list= &sel;
 
1929
          lex->derived_tables= 0;
 
1930
          lex->sql_command= SQLCOM_SHOW_FIELDS;
 
1931
          show_table_list->i_s_requested_object=
 
1932
            schema_table->getRequestedObject();
 
1933
          res= session->openTables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
 
1934
          lex->sql_command= save_sql_command;
 
1935
          /*
 
1936
            XXX->  show_table_list has a flag i_is_requested,
 
1937
            and when it's set, openTables()
 
1938
            can return an error without setting an error message
 
1939
            in Session, which is a hack. This is why we have to
 
1940
            check for res, then for session->is_error() only then
 
1941
            for session->main_da.sql_errno().
 
1942
          */
 
1943
          if (res && session->is_error() &&
 
1944
              session->main_da.sql_errno() == ER_NO_SUCH_TABLE)
 
1945
          {
 
1946
            /*
 
1947
              Hide error for not existing table.
 
1948
              This error can occur for example when we use
 
1949
              where condition with db name and table name and this
 
1950
              table does not exist.
 
1951
            */
 
1952
            res= 0;
 
1953
            session->clear_error();
 
1954
          }
2541
1955
          else
2542
1956
          {
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;
 
1957
            /*
 
1958
              We should use show_table_list->alias instead of
 
1959
              show_table_list->table_name because table_name
 
1960
              could be changed during opening of I_S tables. It's safe
 
1961
              to use alias because alias contains original table name
 
1962
              in this case.
 
1963
            */
 
1964
            session->make_lex_string(&tmp_lex_string, show_table_list->alias,
 
1965
                                     strlen(show_table_list->alias), false);
 
1966
            res= schema_table->processTable(session, show_table_list, table,
 
1967
                                            res, &orig_db_name,
 
1968
                                            &tmp_lex_string);
 
1969
            session->close_tables_for_reopen(&show_table_list);
2613
1970
          }
 
1971
          assert(!lex->query_tables_own_last);
 
1972
          if (res)
 
1973
            goto err;
2614
1974
        }
2615
1975
      }
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
1976
    }
 
1977
    /*
 
1978
      If we have information schema its always the first table and only
 
1979
      the first table. Reset for other tables.
 
1980
    */
 
1981
    with_i_schema= 0;
2622
1982
  }
2623
1983
 
2624
1984
  error= 0;
 
1985
 
2625
1986
err:
2626
1987
  session->restore_backup_open_tables_state(&open_tables_state_backup);
2627
1988
  lex->derived_tables= derived_tables;
2632
1993
}
2633
1994
 
2634
1995
 
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
1996
/**
2896
1997
  @brief    Store field characteristics into appropriate I_S table columns
2897
1998
 
2904
2005
  @return         void
2905
2006
*/
2906
2007
 
2907
 
void store_column_type(Table *table, Field *field, const CHARSET_INFO * const cs,
2908
 
                       uint32_t offset)
 
2008
static void store_column_type(Table *table, Field *field,
 
2009
                              const CHARSET_INFO * const cs,
 
2010
                              uint32_t offset)
2909
2011
{
2910
2012
  bool is_blob;
2911
2013
  int decimals, field_length;
2990
2092
}
2991
2093
 
2992
2094
 
2993
 
static int get_schema_column_record(Session *session, TableList *tables,
 
2095
int plugin::InfoSchemaMethods::processTable(Session *session, TableList *tables,
2994
2096
                                    Table *table, bool res,
2995
2097
                                    LEX_STRING *db_name,
2996
 
                                    LEX_STRING *table_name)
 
2098
                                    LEX_STRING *table_name) const
2997
2099
{
2998
2100
  LEX *lex= session->lex;
2999
2101
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
3000
2102
  const CHARSET_INFO * const cs= system_charset_info;
3001
2103
  Table *show_table;
3002
 
  TABLE_SHARE *show_table_share;
 
2104
  TableShare *show_table_share;
3003
2105
  Field **ptr, *field, *timestamp_field;
3004
2106
  int count;
3005
2107
 
3028
2130
  {
3029
2131
    ptr= show_table->field;
3030
2132
    timestamp_field= show_table->timestamp_field;
3031
 
    show_table->use_all_columns();               // Required for default
3032
2133
  }
3033
2134
  else
3034
2135
  {
3035
2136
    ptr= show_table_share->field;
3036
2137
    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
 
  }
 
2138
  }
 
2139
 
 
2140
  /* For the moment we just set everything to read */
 
2141
  if (!show_table->read_set)
 
2142
  {
 
2143
    show_table->def_read_set.setAll();
 
2144
    show_table->read_set= &show_table->def_read_set;
 
2145
  }
 
2146
  show_table->use_all_columns();               // Required for default
3055
2147
 
3056
2148
  for (; (field= *ptr) ; ptr++)
3057
2149
  {
3070
2162
 
3071
2163
    count++;
3072
2164
    /* Get default row, with all NULL fields set to NULL */
3073
 
    restore_record(table, s->default_values);
 
2165
    table->restoreRecordAsDefault();
3074
2166
 
3075
2167
    table->field[1]->store(db_name->str, db_name->length, cs);
3076
2168
    table->field[2]->store(table_name->str, table_name->length, cs);
3078
2170
                           cs);
3079
2171
    table->field[4]->store((int64_t) count, true);
3080
2172
 
3081
 
    if (get_field_default_value(session, timestamp_field, field, &type, 0))
 
2173
    if (get_field_default_value(timestamp_field, field, &type, 0))
3082
2174
    {
3083
2175
      table->field[5]->store(type.ptr(), type.length(), cs);
3084
2176
      table->field[5]->set_notnull();
3101
2193
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
3102
2194
      table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
3103
2195
                              cs);
3104
 
    if (field->vcol_info)
3105
 
          table->field[16]->store(STRING_WITH_LEN("VIRTUAL"), cs);
3106
2196
    table->field[18]->store(field->comment.str, field->comment.length, cs);
3107
2197
    {
3108
2198
      enum column_format_type column_format= (enum column_format_type)
3123
2213
}
3124
2214
 
3125
2215
 
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)
 
2216
Table *plugin::InfoSchemaMethods::createSchemaTable(Session *session, TableList *table_list)
 
2217
  const
3764
2218
{
3765
2219
  int field_count= 0;
3766
2220
  Item *item;
3767
2221
  Table *table;
3768
2222
  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
2223
  const CHARSET_INFO * const cs= system_charset_info;
 
2224
  const plugin::InfoSchemaTable::Columns &columns= table_list->schema_table->getColumns();
 
2225
  plugin::InfoSchemaTable::Columns::const_iterator iter= columns.begin();
3772
2226
 
3773
 
  for (; fields_info->field_name; fields_info++)
 
2227
  while (iter != columns.end())
3774
2228
  {
3775
 
    switch (fields_info->field_type) {
 
2229
    const plugin::ColumnInfo *column= *iter;
 
2230
    switch (column->getType()) {
3776
2231
    case DRIZZLE_TYPE_LONG:
3777
2232
    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)))
 
2233
      if (!(item= new Item_return_int(column->getName().c_str(),
 
2234
                                      column->getLength(),
 
2235
                                      column->getType(),
 
2236
                                      column->getValue())))
3782
2237
      {
3783
2238
        return(0);
3784
2239
      }
3785
 
      item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
 
2240
      item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
3786
2241
      break;
3787
2242
    case DRIZZLE_TYPE_DATE:
3788
 
    case DRIZZLE_TYPE_TIME:
3789
2243
    case DRIZZLE_TYPE_TIMESTAMP:
3790
2244
    case DRIZZLE_TYPE_DATETIME:
3791
 
      if (!(item=new Item_return_date_time(fields_info->field_name,
3792
 
                                           fields_info->field_type)))
 
2245
      if (!(item=new Item_return_date_time(column->getName().c_str(),
 
2246
                                           column->getType())))
3793
2247
      {
3794
2248
        return(0);
3795
2249
      }
3796
2250
      break;
3797
2251
    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);
 
2252
      if ((item= new Item_float(column->getName().c_str(), 0.0, NOT_FIXED_DEC,
 
2253
                           column->getLength())) == NULL)
 
2254
        return NULL;
3801
2255
      break;
3802
2256
    case DRIZZLE_TYPE_NEWDECIMAL:
3803
 
      if (!(item= new Item_decimal((int64_t) fields_info->value, false)))
 
2257
      if (!(item= new Item_decimal((int64_t) column->getValue(), false)))
3804
2258
      {
3805
2259
        return(0);
3806
2260
      }
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;
 
2261
      item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
 
2262
      item->decimals= column->getLength() % 10;
 
2263
      item->max_length= (column->getLength()/100)%100;
3810
2264
      if (item->unsigned_flag == 0)
3811
2265
        item->max_length+= 1;
3812
2266
      if (item->decimals > 0)
3813
2267
        item->max_length+= 1;
3814
 
      item->set_name(fields_info->field_name,
3815
 
                     strlen(fields_info->field_name), cs);
 
2268
      item->set_name(column->getName().c_str(),
 
2269
                     column->getName().length(), cs);
3816
2270
      break;
3817
2271
    case DRIZZLE_TYPE_BLOB:
3818
 
      if (!(item= new Item_blob(fields_info->field_name,
3819
 
                                fields_info->field_length)))
 
2272
      if (!(item= new Item_blob(column->getName().c_str(),
 
2273
                                column->getLength())))
3820
2274
      {
3821
2275
        return(0);
3822
2276
      }
3823
2277
      break;
3824
2278
    default:
3825
 
      if (!(item= new Item_empty_string("", fields_info->field_length, cs)))
 
2279
      if (!(item= new Item_empty_string("", column->getLength(), cs)))
3826
2280
      {
3827
2281
        return(0);
3828
2282
      }
3829
 
      item->set_name(fields_info->field_name,
3830
 
                     strlen(fields_info->field_name), cs);
 
2283
      item->set_name(column->getName().c_str(),
 
2284
                     column->getName().length(), cs);
3831
2285
      break;
3832
2286
    }
3833
2287
    field_list.push_back(item);
3834
 
    item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL);
 
2288
    item->maybe_null= (column->getFlags() & MY_I_S_MAYBE_NULL);
3835
2289
    field_count++;
 
2290
    ++iter;
3836
2291
  }
3837
 
  TMP_TABLE_PARAM *tmp_table_param =
3838
 
    (TMP_TABLE_PARAM*) (session->alloc(sizeof(TMP_TABLE_PARAM)));
 
2292
  Tmp_Table_Param *tmp_table_param =
 
2293
    (Tmp_Table_Param*) (session->alloc(sizeof(Tmp_Table_Param)));
3839
2294
  tmp_table_param->init();
3840
2295
  tmp_table_param->table_charset= cs;
3841
2296
  tmp_table_param->field_count= field_count;
3842
2297
  tmp_table_param->schema_table= 1;
3843
 
  SELECT_LEX *select_lex= session->lex->current_select;
 
2298
  Select_Lex *select_lex= session->lex->current_select;
3844
2299
  if (!(table= create_tmp_table(session, tmp_table_param,
3845
2300
                                field_list, (order_st*) 0, 0, 0,
3846
2301
                                (select_lex->options | session->options |
3849
2304
    return(0);
3850
2305
  my_bitmap_map* bitmaps=
3851
2306
    (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);
 
2307
  table->def_read_set.init((my_bitmap_map*) bitmaps, field_count);
3854
2308
  table->read_set= &table->def_read_set;
3855
 
  bitmap_clear_all(table->read_set);
 
2309
  table->read_set->clearAll();
3856
2310
  table_list->schema_table_param= tmp_table_param;
3857
2311
  return(table);
3858
2312
}
3864
2318
  Make list of fields for SHOW
3865
2319
 
3866
2320
  SYNOPSIS
3867
 
    make_old_format()
3868
 
    session                     thread handler
 
2321
    plugin::InfoSchemaMethods::oldFormat()
 
2322
    session                     thread Cursor
3869
2323
    schema_table        pointer to 'schema_tables' element
3870
2324
 
3871
2325
  RETURN
3873
2327
   0    success
3874
2328
*/
3875
2329
 
3876
 
int make_old_format(Session *session, ST_SCHEMA_TABLE *schema_table)
 
2330
int plugin::InfoSchemaMethods::oldFormat(Session *session, plugin::InfoSchemaTable *schema_table)
 
2331
  const
3877
2332
{
3878
 
  ST_FIELD_INFO *field_info= schema_table->fields_info;
3879
2333
  Name_resolution_context *context= &session->lex->select_lex.context;
3880
 
  for (; field_info->field_name; field_info++)
 
2334
  const plugin::InfoSchemaTable::Columns columns= schema_table->getColumns();
 
2335
  plugin::InfoSchemaTable::Columns::const_iterator iter= columns.begin();
 
2336
 
 
2337
  while (iter != columns.end())
3881
2338
  {
3882
 
    if (field_info->old_name)
 
2339
    const plugin::ColumnInfo *column= *iter;
 
2340
    if (column->getOldName().length() != 0)
3883
2341
    {
3884
2342
      Item_field *field= new Item_field(context,
3885
 
                                        NULL, NULL, field_info->field_name);
 
2343
                                        NULL, NULL,
 
2344
                                        column->getName().c_str());
3886
2345
      if (field)
3887
2346
      {
3888
 
        field->set_name(field_info->old_name,
3889
 
                        strlen(field_info->old_name),
 
2347
        field->set_name(column->getOldName().c_str(),
 
2348
                        column->getOldName().length(),
3890
2349
                        system_charset_info);
3891
 
        if (add_item_to_list(session, field))
 
2350
        if (session->add_item_to_list(field))
3892
2351
          return 1;
3893
2352
      }
3894
2353
    }
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
 
    }
 
2354
    ++iter;
4014
2355
  }
4015
2356
  return 0;
4016
2357
}
4021
2362
 
4022
2363
  SYNOPSIS
4023
2364
  mysql_schema_table()
4024
 
    session                thread handler
 
2365
    session                thread Cursor
4025
2366
    lex                pointer to LEX
4026
2367
    table_list         pointer to table_list
4027
2368
 
4028
2369
  RETURN
4029
 
    0   success
4030
 
    1   error
 
2370
    true on error
4031
2371
*/
4032
2372
 
4033
 
int mysql_schema_table(Session *session, LEX *, TableList *table_list)
 
2373
bool mysql_schema_table(Session *session, LEX *, TableList *table_list)
4034
2374
{
4035
2375
  Table *table;
4036
 
  if (!(table= table_list->schema_table->create_table(session, table_list)))
4037
 
    return(1);
 
2376
  if (!(table= table_list->schema_table->createSchemaTable(session, table_list)))
 
2377
    return true;
4038
2378
  table->s->tmp_table= SYSTEM_TMP_TABLE;
4039
2379
  /*
4040
2380
    This test is necessary to make
4054
2394
  session->derived_tables= table;
4055
2395
  table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
4056
2396
 
4057
 
  return(0);
 
2397
  return false;
4058
2398
}
4059
2399
 
4060
2400
 
4063
2403
 
4064
2404
  SYNOPSIS
4065
2405
    make_schema_select()
4066
 
    session                  thread handler
4067
 
    sel                  pointer to SELECT_LEX
4068
 
    schema_table_idx     index of 'schema_tables' element
 
2406
    session                  thread Cursor
 
2407
    sel                  pointer to Select_Lex
 
2408
    schema_table_name    name of 'schema_tables' element
4069
2409
 
4070
2410
  RETURN
4071
 
    0   success
4072
 
    1   error
 
2411
    true on error
4073
2412
*/
4074
2413
 
4075
 
int make_schema_select(Session *session, SELECT_LEX *sel,
4076
 
                       enum enum_schema_tables schema_table_idx)
 
2414
bool make_schema_select(Session *session, Select_Lex *sel,
 
2415
                        const string& schema_table_name)
4077
2416
{
4078
 
  ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
 
2417
  plugin::InfoSchemaTable *schema_table= plugin::InfoSchemaTable::getTable(schema_table_name.c_str());
4079
2418
  LEX_STRING db, table;
4080
2419
  /*
4081
2420
     We have to make non const db_name & table_name
4083
2422
  */
4084
2423
  session->make_lex_string(&db, INFORMATION_SCHEMA_NAME.c_str(),
4085
2424
                       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))
 
2425
  session->make_lex_string(&table, schema_table->getTableName().c_str(),
 
2426
                           schema_table->getTableName().length(), 0);
 
2427
  if (schema_table->oldFormat(session, schema_table) ||   /* Handle old syntax */
 
2428
      ! sel->add_table_to_list(session, new Table_ident(db, table), 0, 0, TL_READ))
4091
2429
  {
4092
 
    return(1);
 
2430
    return true;
4093
2431
  }
4094
 
  return(0);
 
2432
  return false;
4095
2433
}
4096
2434
 
4097
2435
 
4111
2449
bool get_schema_tables_result(JOIN *join,
4112
2450
                              enum enum_schema_table_state executed_place)
4113
2451
{
4114
 
  JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
 
2452
  JoinTable *tmp_join_tab= join->join_tab+join->tables;
4115
2453
  Session *session= join->session;
4116
2454
  LEX *lex= session->lex;
4117
2455
  bool result= 0;
4118
2456
 
4119
2457
  session->no_warnings_for_error= 1;
4120
 
  for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++)
 
2458
  for (JoinTable *tab= join->join_tab; tab < tmp_join_tab; tab++)
4121
2459
  {
4122
2460
    if (!tab->table || !tab->table->pos_in_table_list)
4123
2461
      break;
4131
2469
 
4132
2470
      /* skip I_S optimizations specific to get_all_tables */
4133
2471
      if (session->lex->describe &&
4134
 
          (table_list->schema_table->fill_table != get_all_tables))
 
2472
          (table_list->schema_table->isOptimizationPossible() != true))
 
2473
      {
4135
2474
        continue;
 
2475
      }
4136
2476
 
4137
2477
      /*
4138
2478
        If schema table is already processed and
4157
2497
        table_list->table->file->extra(HA_EXTRA_NO_CACHE);
4158
2498
        table_list->table->file->extra(HA_EXTRA_RESET_STATE);
4159
2499
        table_list->table->file->ha_delete_all_rows();
4160
 
        free_io_cache(table_list->table);
4161
 
        filesort_free_buffers(table_list->table,1);
 
2500
        table_list->table->free_io_cache();
 
2501
        table_list->table->filesort_free_buffers(true);
4162
2502
        table_list->table->null_row= 0;
4163
2503
      }
4164
2504
      else
4165
2505
        table_list->table->file->stats.records= 0;
4166
2506
 
4167
 
      if (table_list->schema_table->fill_table(session, table_list,
 
2507
      if (table_list->schema_table->fillTable(session, table_list,
4168
2508
                                               tab->select_cond))
4169
2509
      {
4170
2510
        result= 1;
4180
2520
  session->no_warnings_for_error= 0;
4181
2521
  return(result);
4182
2522
}
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
 
}