~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_show.cc

code clean move Item_func_abs, Item_func_int_exp, Item_func_ln, Item_func_log to functions directory

Show diffs side-by-side

added added

removed removed

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