~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Brian Aker
  • Date: 2010-02-07 01:33:54 UTC
  • Revision ID: brian@gaz-20100207013354-d2pg1n68u5c09pgo
Remove giant include header to its own file.

Show diffs side-by-side

added added

removed removed

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