~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to sql/sql_show.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
 
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 */
 
15
 
 
16
 
 
17
/* Function with list databases, tables or fields */
 
18
 
 
19
#include "mysql_priv.h"
 
20
#include "sql_select.h"                         // For select_describe
 
21
#include "sql_show.h"
 
22
#include "repl_failsafe.h"
 
23
#include "sp.h"
 
24
#include "sp_head.h"
 
25
#include "sql_trigger.h"
 
26
#include "authors.h"
 
27
#include "contributors.h"
 
28
#ifdef HAVE_EVENT_SCHEDULER
 
29
#include "events.h"
 
30
#include "event_data_objects.h"
 
31
#endif
 
32
#include <my_dir.h>
 
33
 
 
34
#define STR_OR_NIL(S) ((S) ? (S) : "<nil>")
 
35
 
 
36
#ifdef WITH_PARTITION_STORAGE_ENGINE
 
37
#include "ha_partition.h"
 
38
#endif
 
39
enum enum_i_s_events_fields
 
40
{
 
41
  ISE_EVENT_CATALOG= 0,
 
42
  ISE_EVENT_SCHEMA,
 
43
  ISE_EVENT_NAME,
 
44
  ISE_DEFINER,
 
45
  ISE_TIME_ZONE,
 
46
  ISE_EVENT_BODY,
 
47
  ISE_EVENT_DEFINITION,
 
48
  ISE_EVENT_TYPE,
 
49
  ISE_EXECUTE_AT,
 
50
  ISE_INTERVAL_VALUE,
 
51
  ISE_INTERVAL_FIELD,
 
52
  ISE_SQL_MODE,
 
53
  ISE_STARTS,
 
54
  ISE_ENDS,
 
55
  ISE_STATUS,
 
56
  ISE_ON_COMPLETION,
 
57
  ISE_CREATED,
 
58
  ISE_LAST_ALTERED,
 
59
  ISE_LAST_EXECUTED,
 
60
  ISE_EVENT_COMMENT,
 
61
  ISE_ORIGINATOR,
 
62
  ISE_CLIENT_CS,
 
63
  ISE_CONNECTION_CL,
 
64
  ISE_DB_CL
 
65
};
 
66
 
 
67
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
68
static const char *grant_names[]={
 
69
  "select","insert","update","delete","create","drop","reload","shutdown",
 
70
  "process","file","grant","references","index","alter"};
 
71
 
 
72
static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
 
73
                               "grant_types",
 
74
                               grant_names, NULL};
 
75
#endif
 
76
 
 
77
static void store_key_options(THD *thd, String *packet, TABLE *table,
 
78
                              KEY *key_info);
 
79
 
 
80
static void
 
81
append_algorithm(TABLE_LIST *table, String *buff);
 
82
 
 
83
static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table);
 
84
 
 
85
/***************************************************************************
 
86
** List all table types supported
 
87
***************************************************************************/
 
88
 
 
89
static int make_version_string(char *buf, int buf_length, uint version)
 
90
{
 
91
  return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff);
 
92
}
 
93
 
 
94
static my_bool show_plugins(THD *thd, plugin_ref plugin,
 
95
                            void *arg)
 
96
{
 
97
  TABLE *table= (TABLE*) arg;
 
98
  struct st_mysql_plugin *plug= plugin_decl(plugin);
 
99
  struct st_plugin_dl *plugin_dl= plugin_dlib(plugin);
 
100
  CHARSET_INFO *cs= system_charset_info;
 
101
  char version_buf[20];
 
102
 
 
103
  restore_record(table, s->default_values);
 
104
 
 
105
  table->field[0]->store(plugin_name(plugin)->str,
 
106
                         plugin_name(plugin)->length, cs);
 
107
 
 
108
  table->field[1]->store(version_buf,
 
109
        make_version_string(version_buf, sizeof(version_buf), plug->version),
 
110
        cs);
 
111
 
 
112
 
 
113
  switch (plugin_state(plugin)) {
 
114
  /* case PLUGIN_IS_FREED: does not happen */
 
115
  case PLUGIN_IS_DELETED:
 
116
    table->field[2]->store(STRING_WITH_LEN("DELETED"), cs);
 
117
    break;
 
118
  case PLUGIN_IS_UNINITIALIZED:
 
119
    table->field[2]->store(STRING_WITH_LEN("INACTIVE"), cs);
 
120
    break;
 
121
  case PLUGIN_IS_READY:
 
122
    table->field[2]->store(STRING_WITH_LEN("ACTIVE"), cs);
 
123
    break;
 
124
  case PLUGIN_IS_DISABLED:
 
125
    table->field[2]->store(STRING_WITH_LEN("DISABLED"), cs);
 
126
    break;
 
127
  default:
 
128
    DBUG_ASSERT(0);
 
129
  }
 
130
 
 
131
  table->field[3]->store(plugin_type_names[plug->type].str,
 
132
                         plugin_type_names[plug->type].length,
 
133
                         cs);
 
134
  table->field[4]->store(version_buf,
 
135
        make_version_string(version_buf, sizeof(version_buf),
 
136
                            *(uint *)plug->info), cs);
 
137
 
 
138
  if (plugin_dl)
 
139
  {
 
140
    table->field[5]->store(plugin_dl->dl.str, plugin_dl->dl.length, cs);
 
141
    table->field[5]->set_notnull();
 
142
    table->field[6]->store(version_buf,
 
143
          make_version_string(version_buf, sizeof(version_buf),
 
144
                              plugin_dl->version),
 
145
          cs);
 
146
    table->field[6]->set_notnull();
 
147
  }
 
148
  else
 
149
  {
 
150
    table->field[5]->set_null();
 
151
    table->field[6]->set_null();
 
152
  }
 
153
 
 
154
 
 
155
  if (plug->author)
 
156
  {
 
157
    table->field[7]->store(plug->author, strlen(plug->author), cs);
 
158
    table->field[7]->set_notnull();
 
159
  }
 
160
  else
 
161
    table->field[7]->set_null();
 
162
 
 
163
  if (plug->descr)
 
164
  {
 
165
    table->field[8]->store(plug->descr, strlen(plug->descr), cs);
 
166
    table->field[8]->set_notnull();
 
167
  }
 
168
  else
 
169
    table->field[8]->set_null();
 
170
 
 
171
  switch (plug->license) {
 
172
  case PLUGIN_LICENSE_GPL:
 
173
    table->field[9]->store(PLUGIN_LICENSE_GPL_STRING, 
 
174
                           strlen(PLUGIN_LICENSE_GPL_STRING), cs);
 
175
    break;
 
176
  case PLUGIN_LICENSE_BSD:
 
177
    table->field[9]->store(PLUGIN_LICENSE_BSD_STRING, 
 
178
                           strlen(PLUGIN_LICENSE_BSD_STRING), cs);
 
179
    break;
 
180
  default:
 
181
    table->field[9]->store(PLUGIN_LICENSE_PROPRIETARY_STRING, 
 
182
                           strlen(PLUGIN_LICENSE_PROPRIETARY_STRING), cs);
 
183
    break;
 
184
  }
 
185
  table->field[9]->set_notnull();
 
186
 
 
187
  return schema_table_store_record(thd, table);
 
188
}
 
189
 
 
190
 
 
191
int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
 
192
{
 
193
  DBUG_ENTER("fill_plugins");
 
194
  TABLE *table= tables->table;
 
195
 
 
196
  if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN,
 
197
                               ~PLUGIN_IS_FREED, table))
 
198
    DBUG_RETURN(1);
 
199
 
 
200
  DBUG_RETURN(0);
 
201
}
 
202
 
 
203
 
 
204
/***************************************************************************
 
205
** List all Authors.
 
206
** If you can update it, you get to be in it :)
 
207
***************************************************************************/
 
208
 
 
209
bool mysqld_show_authors(THD *thd)
 
210
{
 
211
  List<Item> field_list;
 
212
  Protocol *protocol= thd->protocol;
 
213
  DBUG_ENTER("mysqld_show_authors");
 
214
 
 
215
  field_list.push_back(new Item_empty_string("Name",40));
 
216
  field_list.push_back(new Item_empty_string("Location",40));
 
217
  field_list.push_back(new Item_empty_string("Comment",80));
 
218
 
 
219
  if (protocol->send_fields(&field_list,
 
220
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
221
    DBUG_RETURN(TRUE);
 
222
 
 
223
  show_table_authors_st *authors;
 
224
  for (authors= show_table_authors; authors->name; authors++)
 
225
  {
 
226
    protocol->prepare_for_resend();
 
227
    protocol->store(authors->name, system_charset_info);
 
228
    protocol->store(authors->location, system_charset_info);
 
229
    protocol->store(authors->comment, system_charset_info);
 
230
    if (protocol->write())
 
231
      DBUG_RETURN(TRUE);
 
232
  }
 
233
  my_eof(thd);
 
234
  DBUG_RETURN(FALSE);
 
235
}
 
236
 
 
237
 
 
238
/***************************************************************************
 
239
** List all Contributors.
 
240
** Please get permission before updating
 
241
***************************************************************************/
 
242
 
 
243
bool mysqld_show_contributors(THD *thd)
 
244
{
 
245
  List<Item> field_list;
 
246
  Protocol *protocol= thd->protocol;
 
247
  DBUG_ENTER("mysqld_show_contributors");
 
248
 
 
249
  field_list.push_back(new Item_empty_string("Name",40));
 
250
  field_list.push_back(new Item_empty_string("Location",40));
 
251
  field_list.push_back(new Item_empty_string("Comment",80));
 
252
 
 
253
  if (protocol->send_fields(&field_list,
 
254
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
255
    DBUG_RETURN(TRUE);
 
256
 
 
257
  show_table_contributors_st *contributors;
 
258
  for (contributors= show_table_contributors; contributors->name; contributors++)
 
259
  {
 
260
    protocol->prepare_for_resend();
 
261
    protocol->store(contributors->name, system_charset_info);
 
262
    protocol->store(contributors->location, system_charset_info);
 
263
    protocol->store(contributors->comment, system_charset_info);
 
264
    if (protocol->write())
 
265
      DBUG_RETURN(TRUE);
 
266
  }
 
267
  my_eof(thd);
 
268
  DBUG_RETURN(FALSE);
 
269
}
 
270
 
 
271
 
 
272
/***************************************************************************
 
273
 List all privileges supported
 
274
***************************************************************************/
 
275
 
 
276
struct show_privileges_st {
 
277
  const char *privilege;
 
278
  const char *context;
 
279
  const char *comment;
 
280
};
 
281
 
 
282
static struct show_privileges_st sys_privileges[]=
 
283
{
 
284
  {"Alter", "Tables",  "To alter the table"},
 
285
  {"Alter routine", "Functions,Procedures",  "To alter or drop stored functions/procedures"},
 
286
  {"Create", "Databases,Tables,Indexes",  "To create new databases and tables"},
 
287
  {"Create routine","Databases","To use CREATE FUNCTION/PROCEDURE"},
 
288
  {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
 
289
  {"Create view", "Tables",  "To create new views"},
 
290
  {"Create user", "Server Admin",  "To create new users"},
 
291
  {"Delete", "Tables",  "To delete existing rows"},
 
292
  {"Drop", "Databases,Tables", "To drop databases, tables, and views"},
 
293
#ifdef HAVE_EVENT_SCHEDULER
 
294
  {"Event","Server Admin","To create, alter, drop and execute events"},
 
295
#endif
 
296
  {"Execute", "Functions,Procedures", "To execute stored routines"},
 
297
  {"File", "File access on server",   "To read and write files on the server"},
 
298
  {"Grant option",  "Databases,Tables,Functions,Procedures", "To give to other users those privileges you possess"},
 
299
  {"Index", "Tables",  "To create or drop indexes"},
 
300
  {"Insert", "Tables",  "To insert data into tables"},
 
301
  {"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"},
 
302
  {"Process", "Server Admin", "To view the plain text of currently executing queries"},
 
303
  {"References", "Databases,Tables", "To have references on tables"},
 
304
  {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"},
 
305
  {"Replication client","Server Admin","To ask where the slave or master servers are"},
 
306
  {"Replication slave","Server Admin","To read binary log events from the master"},
 
307
  {"Select", "Tables",  "To retrieve rows from table"},
 
308
  {"Show databases","Server Admin","To see all databases with SHOW DATABASES"},
 
309
  {"Show view","Tables","To see views with SHOW CREATE VIEW"},
 
310
  {"Shutdown","Server Admin", "To shut down the server"},
 
311
  {"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."},
 
312
  {"Trigger","Tables", "To use triggers"},
 
313
  {"Update", "Tables",  "To update existing rows"},
 
314
  {"Usage","Server Admin","No privileges - allow connect only"},
 
315
  {NullS, NullS, NullS}
 
316
};
 
317
 
 
318
bool mysqld_show_privileges(THD *thd)
 
319
{
 
320
  List<Item> field_list;
 
321
  Protocol *protocol= thd->protocol;
 
322
  DBUG_ENTER("mysqld_show_privileges");
 
323
 
 
324
  field_list.push_back(new Item_empty_string("Privilege",10));
 
325
  field_list.push_back(new Item_empty_string("Context",15));
 
326
  field_list.push_back(new Item_empty_string("Comment",NAME_CHAR_LEN));
 
327
 
 
328
  if (protocol->send_fields(&field_list,
 
329
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
330
    DBUG_RETURN(TRUE);
 
331
 
 
332
  show_privileges_st *privilege= sys_privileges;
 
333
  for (privilege= sys_privileges; privilege->privilege ; privilege++)
 
334
  {
 
335
    protocol->prepare_for_resend();
 
336
    protocol->store(privilege->privilege, system_charset_info);
 
337
    protocol->store(privilege->context, system_charset_info);
 
338
    protocol->store(privilege->comment, system_charset_info);
 
339
    if (protocol->write())
 
340
      DBUG_RETURN(TRUE);
 
341
  }
 
342
  my_eof(thd);
 
343
  DBUG_RETURN(FALSE);
 
344
}
 
345
 
 
346
 
 
347
/***************************************************************************
 
348
  List all column types
 
349
***************************************************************************/
 
350
 
 
351
struct show_column_type_st
 
352
{
 
353
  const char *type;
 
354
  uint size;
 
355
  const char *min_value;
 
356
  const char *max_value;
 
357
  uint precision;
 
358
  uint scale;
 
359
  const char *nullable;
 
360
  const char *auto_increment;
 
361
  const char *unsigned_attr;
 
362
  const char *zerofill;
 
363
  const char *searchable;
 
364
  const char *case_sensitivity;
 
365
  const char *default_value;
 
366
  const char *comment;
 
367
};
 
368
 
 
369
/* TODO: Add remaning types */
 
370
 
 
371
static struct show_column_type_st sys_column_types[]=
 
372
{
 
373
  {"tinyint",
 
374
    1,  "-128",  "127",  0,  0,  "YES",  "YES",
 
375
    "NO",   "YES", "YES",  "NO",  "NULL,0",
 
376
    "A very small integer"},
 
377
  {"tinyint unsigned",
 
378
    1,  "0"   ,  "255",  0,  0,  "YES",  "YES",
 
379
    "YES",  "YES",  "YES",  "NO",  "NULL,0",
 
380
    "A very small integer"},
 
381
};
 
382
 
 
383
bool mysqld_show_column_types(THD *thd)
 
384
{
 
385
  List<Item> field_list;
 
386
  Protocol *protocol= thd->protocol;
 
387
  DBUG_ENTER("mysqld_show_column_types");
 
388
 
 
389
  field_list.push_back(new Item_empty_string("Type",30));
 
390
  field_list.push_back(new Item_int("Size",(longlong) 1,
 
391
                                    MY_INT64_NUM_DECIMAL_DIGITS));
 
392
  field_list.push_back(new Item_empty_string("Min_Value",20));
 
393
  field_list.push_back(new Item_empty_string("Max_Value",20));
 
394
  field_list.push_back(new Item_return_int("Prec", 4, MYSQL_TYPE_SHORT));
 
395
  field_list.push_back(new Item_return_int("Scale", 4, MYSQL_TYPE_SHORT));
 
396
  field_list.push_back(new Item_empty_string("Nullable",4));
 
397
  field_list.push_back(new Item_empty_string("Auto_Increment",4));
 
398
  field_list.push_back(new Item_empty_string("Unsigned",4));
 
399
  field_list.push_back(new Item_empty_string("Zerofill",4));
 
400
  field_list.push_back(new Item_empty_string("Searchable",4));
 
401
  field_list.push_back(new Item_empty_string("Case_Sensitive",4));
 
402
  field_list.push_back(new Item_empty_string("Default",NAME_CHAR_LEN));
 
403
  field_list.push_back(new Item_empty_string("Comment",NAME_CHAR_LEN));
 
404
 
 
405
  if (protocol->send_fields(&field_list,
 
406
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
407
    DBUG_RETURN(TRUE);
 
408
 
 
409
  /* TODO: Change the loop to not use 'i' */
 
410
  for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
 
411
  {
 
412
    protocol->prepare_for_resend();
 
413
    protocol->store(sys_column_types[i].type, system_charset_info);
 
414
    protocol->store((ulonglong) sys_column_types[i].size);
 
415
    protocol->store(sys_column_types[i].min_value, system_charset_info);
 
416
    protocol->store(sys_column_types[i].max_value, system_charset_info);
 
417
    protocol->store_short((longlong) sys_column_types[i].precision);
 
418
    protocol->store_short((longlong) sys_column_types[i].scale);
 
419
    protocol->store(sys_column_types[i].nullable, system_charset_info);
 
420
    protocol->store(sys_column_types[i].auto_increment, system_charset_info);
 
421
    protocol->store(sys_column_types[i].unsigned_attr, system_charset_info);
 
422
    protocol->store(sys_column_types[i].zerofill, system_charset_info);
 
423
    protocol->store(sys_column_types[i].searchable, system_charset_info);
 
424
    protocol->store(sys_column_types[i].case_sensitivity, system_charset_info);
 
425
    protocol->store(sys_column_types[i].default_value, system_charset_info);
 
426
    protocol->store(sys_column_types[i].comment, system_charset_info);
 
427
    if (protocol->write())
 
428
      DBUG_RETURN(TRUE);
 
429
  }
 
430
  my_eof(thd);
 
431
  DBUG_RETURN(FALSE);
 
432
}
 
433
 
 
434
 
 
435
/*
 
436
  find_files() - find files in a given directory.
 
437
 
 
438
  SYNOPSIS
 
439
    find_files()
 
440
    thd                 thread handler
 
441
    files               put found files in this list
 
442
    db                  database name to set in TABLE_LIST structure
 
443
    path                path to database
 
444
    wild                filter for found files
 
445
    dir                 read databases in path if TRUE, read .frm files in
 
446
                        database otherwise
 
447
 
 
448
  RETURN
 
449
    FIND_FILES_OK       success
 
450
    FIND_FILES_OOM      out of memory error
 
451
    FIND_FILES_DIR      no such directory, or directory can't be read
 
452
*/
 
453
 
 
454
 
 
455
find_files_result
 
456
find_files(THD *thd, List<LEX_STRING> *files, const char *db,
 
457
           const char *path, const char *wild, bool dir)
 
458
{
 
459
  uint i;
 
460
  char *ext;
 
461
  MY_DIR *dirp;
 
462
  FILEINFO *file;
 
463
  LEX_STRING *file_name= 0;
 
464
  uint file_name_len;
 
465
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
466
  uint col_access=thd->col_access;
 
467
#endif
 
468
  uint wild_length= 0;
 
469
  TABLE_LIST table_list;
 
470
  DBUG_ENTER("find_files");
 
471
 
 
472
  if (wild)
 
473
  {
 
474
    if (!wild[0])
 
475
      wild= 0;
 
476
    else
 
477
      wild_length= strlen(wild);
 
478
  }
 
479
 
 
480
 
 
481
 
 
482
  bzero((char*) &table_list,sizeof(table_list));
 
483
 
 
484
  if (!(dirp = my_dir(path,MYF(dir ? MY_WANT_STAT : 0))))
 
485
  {
 
486
    if (my_errno == ENOENT)
 
487
      my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), db);
 
488
    else
 
489
      my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), path, my_errno);
 
490
    DBUG_RETURN(FIND_FILES_DIR);
 
491
  }
 
492
 
 
493
  for (i=0 ; i < (uint) dirp->number_off_files  ; i++)
 
494
  {
 
495
    char uname[NAME_LEN + 1];                   /* Unencoded name */
 
496
    file=dirp->dir_entry+i;
 
497
    if (dir)
 
498
    {                                           /* Return databases */
 
499
      if ((file->name[0] == '.' && 
 
500
          ((file->name[1] == '.' && file->name[2] == '\0') ||
 
501
            file->name[1] == '\0')))
 
502
        continue;                               /* . or .. */
 
503
#ifdef USE_SYMDIR
 
504
      char *ext;
 
505
      char buff[FN_REFLEN];
 
506
      if (my_use_symdir && !strcmp(ext=fn_ext(file->name), ".sym"))
 
507
      {
 
508
        /* Only show the sym file if it points to a directory */
 
509
        char *end;
 
510
        *ext=0;                                 /* Remove extension */
 
511
        unpack_dirname(buff, file->name);
 
512
        end= strend(buff);
 
513
        if (end != buff && end[-1] == FN_LIBCHAR)
 
514
          end[-1]= 0;                           // Remove end FN_LIBCHAR
 
515
        if (!my_stat(buff, file->mystat, MYF(0)))
 
516
               continue;
 
517
       }
 
518
#endif
 
519
      if (!MY_S_ISDIR(file->mystat->st_mode))
 
520
        continue;
 
521
 
 
522
      file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
 
523
      if (wild && wild_compare(uname, wild, 0))
 
524
        continue;
 
525
      if (!(file_name= 
 
526
            thd->make_lex_string(file_name, uname, file_name_len, TRUE)))
 
527
      {
 
528
        my_dirend(dirp);
 
529
        DBUG_RETURN(FIND_FILES_OOM);
 
530
      }
 
531
    }
 
532
    else
 
533
    {
 
534
        // Return only .frm files which aren't temp files.
 
535
      if (my_strcasecmp(system_charset_info, ext=fn_rext(file->name),reg_ext) ||
 
536
          is_prefix(file->name, tmp_file_prefix))
 
537
        continue;
 
538
      *ext=0;
 
539
      file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
 
540
      if (wild)
 
541
      {
 
542
        if (lower_case_table_names)
 
543
        {
 
544
          if (my_wildcmp(files_charset_info,
 
545
                         uname, uname + file_name_len,
 
546
                         wild, wild + wild_length,
 
547
                         wild_prefix, wild_one,wild_many))
 
548
            continue;
 
549
        }
 
550
        else if (wild_compare(uname, wild, 0))
 
551
          continue;
 
552
      }
 
553
    }
 
554
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
555
    /* Don't show tables where we don't have any privileges */
 
556
    if (db && !(col_access & TABLE_ACLS))
 
557
    {
 
558
      table_list.db= (char*) db;
 
559
      table_list.db_length= strlen(db);
 
560
      table_list.table_name= uname;
 
561
      table_list.table_name_length= file_name_len;
 
562
      table_list.grant.privilege=col_access;
 
563
      if (check_grant(thd, TABLE_ACLS, &table_list, 1, 1, 1))
 
564
        continue;
 
565
    }
 
566
#endif
 
567
    if (!(file_name= 
 
568
          thd->make_lex_string(file_name, uname, file_name_len, TRUE)) ||
 
569
        files->push_back(file_name))
 
570
    {
 
571
      my_dirend(dirp);
 
572
      DBUG_RETURN(FIND_FILES_OOM);
 
573
    }
 
574
  }
 
575
  DBUG_PRINT("info",("found: %d files", files->elements));
 
576
  my_dirend(dirp);
 
577
 
 
578
  VOID(ha_find_files(thd, db, path, wild, dir, files));
 
579
 
 
580
  DBUG_RETURN(FIND_FILES_OK);
 
581
}
 
582
 
 
583
 
 
584
/**
 
585
   An Internal_error_handler that suppresses errors regarding views'
 
586
   underlying tables that occur during privilege checking within SHOW CREATE
 
587
   VIEW commands. This happens in the cases when
 
588
 
 
589
   - A view's underlying table (e.g. referenced in its SELECT list) does not
 
590
     exist. There should not be an error as no attempt was made to access it
 
591
     per se.
 
592
 
 
593
   - Access is denied for some table, column, function or stored procedure
 
594
     such as mentioned above. This error gets raised automatically, since we
 
595
     can't untangle its access checking from that of the view itself.
 
596
 */
 
597
class Show_create_error_handler : public Internal_error_handler {
 
598
  
 
599
  TABLE_LIST *m_top_view;
 
600
  bool m_handling;
 
601
  Security_context *m_sctx;
 
602
 
 
603
  char m_view_access_denied_message[MYSQL_ERRMSG_SIZE];
 
604
  char *m_view_access_denied_message_ptr;
 
605
 
 
606
public:
 
607
 
 
608
  /**
 
609
     Creates a new Show_create_error_handler for the particular security
 
610
     context and view. 
 
611
 
 
612
     @thd Thread context, used for security context information if needed.
 
613
     @top_view The view. We do not verify at this point that top_view is in
 
614
     fact a view since, alas, these things do not stay constant.
 
615
  */
 
616
  explicit Show_create_error_handler(THD *thd, TABLE_LIST *top_view) : 
 
617
    m_top_view(top_view), m_handling(FALSE),
 
618
    m_view_access_denied_message_ptr(NULL) 
 
619
  {
 
620
    
 
621
    m_sctx = test(m_top_view->security_ctx) ?
 
622
      m_top_view->security_ctx : thd->security_ctx;
 
623
  }
 
624
 
 
625
  /**
 
626
     Lazy instantiation of 'view access denied' message. The purpose of the
 
627
     Show_create_error_handler is to hide details of underlying tables for
 
628
     which we have no privileges behind ER_VIEW_INVALID messages. But this
 
629
     obviously does not apply if we lack privileges on the view itself.
 
630
     Unfortunately the information about for which table privilege checking
 
631
     failed is not available at this point. The only way for us to check is by
 
632
     reconstructing the actual error message and see if it's the same.
 
633
  */
 
634
  char* get_view_access_denied_message() 
 
635
  {
 
636
    if (!m_view_access_denied_message_ptr)
 
637
    {
 
638
      m_view_access_denied_message_ptr= m_view_access_denied_message;
 
639
      my_snprintf(m_view_access_denied_message, MYSQL_ERRMSG_SIZE,
 
640
                  ER(ER_TABLEACCESS_DENIED_ERROR), "SHOW VIEW",
 
641
                  m_sctx->priv_user,
 
642
                  m_sctx->host_or_ip, m_top_view->get_table_name());
 
643
    }
 
644
    return m_view_access_denied_message_ptr;
 
645
  }
 
646
 
 
647
  bool handle_error(uint sql_errno, const char *message, 
 
648
                    MYSQL_ERROR::enum_warning_level level, THD *thd) {
 
649
    /* 
 
650
       The handler does not handle the errors raised by itself.
 
651
       At this point we know if top_view is really a view.
 
652
    */
 
653
    if (m_handling || !m_top_view->view)
 
654
      return FALSE;
 
655
 
 
656
    m_handling= TRUE;
 
657
 
 
658
    bool is_handled;
 
659
    
 
660
    switch (sql_errno)
 
661
    {
 
662
    case ER_TABLEACCESS_DENIED_ERROR:
 
663
      if (!strcmp(get_view_access_denied_message(), message))
 
664
      {
 
665
        /* Access to top view is not granted, don't interfere. */
 
666
        is_handled= FALSE;
 
667
        break;
 
668
      }
 
669
    case ER_COLUMNACCESS_DENIED_ERROR:
 
670
    case ER_VIEW_NO_EXPLAIN: /* Error was anonymized, ignore all the same. */
 
671
    case ER_PROCACCESS_DENIED_ERROR:
 
672
      is_handled= TRUE;
 
673
      break;
 
674
 
 
675
    case ER_NO_SUCH_TABLE:
 
676
      /* Established behavior: warn if underlying tables are missing. */
 
677
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
 
678
                          ER_VIEW_INVALID,
 
679
                          ER(ER_VIEW_INVALID),
 
680
                          m_top_view->get_db_name(),
 
681
                          m_top_view->get_table_name());
 
682
      is_handled= TRUE;
 
683
      break;
 
684
 
 
685
    case ER_SP_DOES_NOT_EXIST:
 
686
      /* Established behavior: warn if underlying functions are missing. */
 
687
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
 
688
                          ER_VIEW_INVALID,
 
689
                          ER(ER_VIEW_INVALID),
 
690
                          m_top_view->get_db_name(),
 
691
                          m_top_view->get_table_name());
 
692
      is_handled= TRUE;
 
693
      break;
 
694
    default:
 
695
      is_handled= FALSE;
 
696
    }
 
697
 
 
698
    m_handling= FALSE;
 
699
    return is_handled;
 
700
  }
 
701
};
 
702
 
 
703
 
 
704
bool
 
705
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
 
706
{
 
707
  Protocol *protocol= thd->protocol;
 
708
  char buff[2048];
 
709
  String buffer(buff, sizeof(buff), system_charset_info);
 
710
  DBUG_ENTER("mysqld_show_create");
 
711
  DBUG_PRINT("enter",("db: %s  table: %s",table_list->db,
 
712
                      table_list->table_name));
 
713
 
 
714
  /* We want to preserve the tree for views. */
 
715
  thd->lex->view_prepare_mode= TRUE;
 
716
 
 
717
  {
 
718
    Show_create_error_handler view_error_suppressor(thd, table_list);
 
719
    thd->push_internal_handler(&view_error_suppressor);
 
720
    bool error= open_normal_and_derived_tables(thd, table_list, 0);
 
721
    thd->pop_internal_handler();
 
722
    if (error && (thd->killed || thd->main_da.is_error()))
 
723
      DBUG_RETURN(TRUE);
 
724
  }
 
725
 
 
726
  /* TODO: add environment variables show when it become possible */
 
727
  if (thd->lex->only_view && !table_list->view)
 
728
  {
 
729
    my_error(ER_WRONG_OBJECT, MYF(0),
 
730
             table_list->db, table_list->table_name, "VIEW");
 
731
    DBUG_RETURN(TRUE);
 
732
  }
 
733
 
 
734
  buffer.length(0);
 
735
 
 
736
  if (table_list->view)
 
737
    buffer.set_charset(table_list->view_creation_ctx->get_client_cs());
 
738
 
 
739
  if ((table_list->view ?
 
740
       view_store_create_info(thd, table_list, &buffer) :
 
741
       store_create_info(thd, table_list, &buffer, NULL,
 
742
                         FALSE /* show_database */)))
 
743
    DBUG_RETURN(TRUE);
 
744
 
 
745
  List<Item> field_list;
 
746
  if (table_list->view)
 
747
  {
 
748
    field_list.push_back(new Item_empty_string("View",NAME_CHAR_LEN));
 
749
    field_list.push_back(new Item_empty_string("Create View",
 
750
                                               max(buffer.length(),1024)));
 
751
    field_list.push_back(new Item_empty_string("character_set_client",
 
752
                                               MY_CS_NAME_SIZE));
 
753
    field_list.push_back(new Item_empty_string("collation_connection",
 
754
                                               MY_CS_NAME_SIZE));
 
755
  }
 
756
  else
 
757
  {
 
758
    field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
 
759
    // 1024 is for not to confuse old clients
 
760
    field_list.push_back(new Item_empty_string("Create Table",
 
761
                                               max(buffer.length(),1024)));
 
762
  }
 
763
 
 
764
  if (protocol->send_fields(&field_list,
 
765
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
766
    DBUG_RETURN(TRUE);
 
767
  protocol->prepare_for_resend();
 
768
  if (table_list->view)
 
769
    protocol->store(table_list->view_name.str, system_charset_info);
 
770
  else
 
771
  {
 
772
    if (table_list->schema_table)
 
773
      protocol->store(table_list->schema_table->table_name,
 
774
                      system_charset_info);
 
775
    else
 
776
      protocol->store(table_list->table->alias, system_charset_info);
 
777
  }
 
778
 
 
779
  if (table_list->view)
 
780
  {
 
781
    protocol->store(buffer.ptr(), buffer.length(),
 
782
                    table_list->view_creation_ctx->get_client_cs());
 
783
 
 
784
    protocol->store(table_list->view_creation_ctx->get_client_cs()->csname,
 
785
                    system_charset_info);
 
786
 
 
787
    protocol->store(table_list->view_creation_ctx->get_connection_cl()->name,
 
788
                    system_charset_info);
 
789
  }
 
790
  else
 
791
    protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
 
792
 
 
793
  if (protocol->write())
 
794
    DBUG_RETURN(TRUE);
 
795
 
 
796
  my_eof(thd);
 
797
  DBUG_RETURN(FALSE);
 
798
}
 
799
 
 
800
bool mysqld_show_create_db(THD *thd, char *dbname,
 
801
                           HA_CREATE_INFO *create_info)
 
802
{
 
803
  char buff[2048];
 
804
  String buffer(buff, sizeof(buff), system_charset_info);
 
805
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
806
  Security_context *sctx= thd->security_ctx;
 
807
  uint db_access;
 
808
#endif
 
809
  HA_CREATE_INFO create;
 
810
  uint create_options = create_info ? create_info->options : 0;
 
811
  Protocol *protocol=thd->protocol;
 
812
  DBUG_ENTER("mysql_show_create_db");
 
813
 
 
814
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
815
  if (test_all_bits(sctx->master_access, DB_ACLS))
 
816
    db_access=DB_ACLS;
 
817
  else
 
818
    db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname, 0) |
 
819
                sctx->master_access);
 
820
  if (!(db_access & DB_ACLS) && check_grant_db(thd,dbname))
 
821
  {
 
822
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
 
823
             sctx->priv_user, sctx->host_or_ip, dbname);
 
824
    general_log_print(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
 
825
                      sctx->priv_user, sctx->host_or_ip, dbname);
 
826
    DBUG_RETURN(TRUE);
 
827
  }
 
828
#endif
 
829
  if (is_schema_db(dbname))
 
830
  {
 
831
    dbname= INFORMATION_SCHEMA_NAME.str;
 
832
    create.default_table_charset= system_charset_info;
 
833
  }
 
834
  else
 
835
  {
 
836
    if (check_db_dir_existence(dbname))
 
837
    {
 
838
      my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
 
839
      DBUG_RETURN(TRUE);
 
840
    }
 
841
 
 
842
    load_db_opt_by_name(thd, dbname, &create);
 
843
  }
 
844
  List<Item> field_list;
 
845
  field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
 
846
  field_list.push_back(new Item_empty_string("Create Database",1024));
 
847
 
 
848
  if (protocol->send_fields(&field_list,
 
849
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
850
    DBUG_RETURN(TRUE);
 
851
 
 
852
  protocol->prepare_for_resend();
 
853
  protocol->store(dbname, strlen(dbname), system_charset_info);
 
854
  buffer.length(0);
 
855
  buffer.append(STRING_WITH_LEN("CREATE DATABASE "));
 
856
  if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
 
857
    buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ "));
 
858
  append_identifier(thd, &buffer, dbname, strlen(dbname));
 
859
 
 
860
  if (create.default_table_charset)
 
861
  {
 
862
    buffer.append(STRING_WITH_LEN(" /*!40100"));
 
863
    buffer.append(STRING_WITH_LEN(" DEFAULT CHARACTER SET "));
 
864
    buffer.append(create.default_table_charset->csname);
 
865
    if (!(create.default_table_charset->state & MY_CS_PRIMARY))
 
866
    {
 
867
      buffer.append(STRING_WITH_LEN(" COLLATE "));
 
868
      buffer.append(create.default_table_charset->name);
 
869
    }
 
870
    buffer.append(STRING_WITH_LEN(" */"));
 
871
  }
 
872
  protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
 
873
 
 
874
  if (protocol->write())
 
875
    DBUG_RETURN(TRUE);
 
876
  my_eof(thd);
 
877
  DBUG_RETURN(FALSE);
 
878
}
 
879
 
 
880
 
 
881
 
 
882
/****************************************************************************
 
883
  Return only fields for API mysql_list_fields
 
884
  Use "show table wildcard" in mysql instead of this
 
885
****************************************************************************/
 
886
 
 
887
void
 
888
mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
 
889
{
 
890
  TABLE *table;
 
891
  DBUG_ENTER("mysqld_list_fields");
 
892
  DBUG_PRINT("enter",("table: %s",table_list->table_name));
 
893
 
 
894
  if (open_normal_and_derived_tables(thd, table_list, 0))
 
895
    DBUG_VOID_RETURN;
 
896
  table= table_list->table;
 
897
 
 
898
  List<Item> field_list;
 
899
 
 
900
  Field **ptr,*field;
 
901
  for (ptr=table->field ; (field= *ptr); ptr++)
 
902
  {
 
903
    if (!wild || !wild[0] || 
 
904
        !wild_case_compare(system_charset_info, field->field_name,wild))
 
905
    {
 
906
      if (table_list->view)
 
907
        field_list.push_back(new Item_ident_for_show(field,
 
908
                                                     table_list->view_db.str,
 
909
                                                     table_list->view_name.str));
 
910
      else
 
911
        field_list.push_back(new Item_field(field));
 
912
    }
 
913
  }
 
914
  restore_record(table, s->default_values);              // Get empty record
 
915
  table->use_all_columns();
 
916
  if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS))
 
917
    DBUG_VOID_RETURN;
 
918
  my_eof(thd);
 
919
  DBUG_VOID_RETURN;
 
920
}
 
921
 
 
922
 
 
923
int
 
924
mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd)
 
925
{
 
926
  Protocol *protocol= thd->protocol;
 
927
  String *packet= protocol->storage_packet();
 
928
  DBUG_ENTER("mysqld_dump_create_info");
 
929
  DBUG_PRINT("enter",("table: %s",table_list->table->s->table_name.str));
 
930
 
 
931
  protocol->prepare_for_resend();
 
932
  if (store_create_info(thd, table_list, packet, NULL,
 
933
                        FALSE /* show_database */))
 
934
    DBUG_RETURN(-1);
 
935
 
 
936
  if (fd < 0)
 
937
  {
 
938
    if (protocol->write())
 
939
      DBUG_RETURN(-1);
 
940
    protocol->flush();
 
941
  }
 
942
  else
 
943
  {
 
944
    if (my_write(fd, (const uchar*) packet->ptr(), packet->length(),
 
945
                 MYF(MY_WME)))
 
946
      DBUG_RETURN(-1);
 
947
  }
 
948
  DBUG_RETURN(0);
 
949
}
 
950
 
 
951
/*
 
952
  Go through all character combinations and ensure that sql_lex.cc can
 
953
  parse it as an identifier.
 
954
 
 
955
  SYNOPSIS
 
956
  require_quotes()
 
957
  name                  attribute name
 
958
  name_length           length of name
 
959
 
 
960
  RETURN
 
961
    #   Pointer to conflicting character
 
962
    0   No conflicting character
 
963
*/
 
964
 
 
965
static const char *require_quotes(const char *name, uint name_length)
 
966
{
 
967
  uint length;
 
968
  bool pure_digit= TRUE;
 
969
  const char *end= name + name_length;
 
970
 
 
971
  for (; name < end ; name++)
 
972
  {
 
973
    uchar chr= (uchar) *name;
 
974
    length= my_mbcharlen(system_charset_info, chr);
 
975
    if (length == 1 && !system_charset_info->ident_map[chr])
 
976
      return name;
 
977
    if (length == 1 && (chr < '0' || chr > '9'))
 
978
      pure_digit= FALSE;
 
979
  }
 
980
  if (pure_digit)
 
981
    return name;
 
982
  return 0;
 
983
}
 
984
 
 
985
 
 
986
/*
 
987
  Quote the given identifier if needed and append it to the target string.
 
988
  If the given identifier is empty, it will be quoted.
 
989
 
 
990
  SYNOPSIS
 
991
  append_identifier()
 
992
  thd                   thread handler
 
993
  packet                target string
 
994
  name                  the identifier to be appended
 
995
  name_length           length of the appending identifier
 
996
*/
 
997
 
 
998
void
 
999
append_identifier(THD *thd, String *packet, const char *name, uint length)
 
1000
{
 
1001
  const char *name_end;
 
1002
  char quote_char;
 
1003
  int q= get_quote_char_for_identifier(thd, name, length);
 
1004
 
 
1005
  if (q == EOF)
 
1006
  {
 
1007
    packet->append(name, length, packet->charset());
 
1008
    return;
 
1009
  }
 
1010
 
 
1011
  /*
 
1012
    The identifier must be quoted as it includes a quote character or
 
1013
   it's a keyword
 
1014
  */
 
1015
 
 
1016
  VOID(packet->reserve(length*2 + 2));
 
1017
  quote_char= (char) q;
 
1018
  packet->append(&quote_char, 1, system_charset_info);
 
1019
 
 
1020
  for (name_end= name+length ; name < name_end ; name+= length)
 
1021
  {
 
1022
    uchar chr= (uchar) *name;
 
1023
    length= my_mbcharlen(system_charset_info, chr);
 
1024
    /*
 
1025
      my_mbcharlen can return 0 on a wrong multibyte
 
1026
      sequence. It is possible when upgrading from 4.0,
 
1027
      and identifier contains some accented characters.
 
1028
      The manual says it does not work. So we'll just
 
1029
      change length to 1 not to hang in the endless loop.
 
1030
    */
 
1031
    if (!length)
 
1032
      length= 1;
 
1033
    if (length == 1 && chr == (uchar) quote_char)
 
1034
      packet->append(&quote_char, 1, system_charset_info);
 
1035
    packet->append(name, length, system_charset_info);
 
1036
  }
 
1037
  packet->append(&quote_char, 1, system_charset_info);
 
1038
}
 
1039
 
 
1040
 
 
1041
/*
 
1042
  Get the quote character for displaying an identifier.
 
1043
 
 
1044
  SYNOPSIS
 
1045
    get_quote_char_for_identifier()
 
1046
    thd         Thread handler
 
1047
    name        name to quote
 
1048
    length      length of name
 
1049
 
 
1050
  IMPLEMENTATION
 
1051
    Force quoting in the following cases:
 
1052
      - name is empty (for one, it is possible when we use this function for
 
1053
        quoting user and host names for DEFINER clause);
 
1054
      - name is a keyword;
 
1055
      - name includes a special character;
 
1056
    Otherwise identifier is quoted only if the option OPTION_QUOTE_SHOW_CREATE
 
1057
    is set.
 
1058
 
 
1059
  RETURN
 
1060
    EOF   No quote character is needed
 
1061
    #     Quote character
 
1062
*/
 
1063
 
 
1064
int get_quote_char_for_identifier(THD *thd, const char *name, uint length)
 
1065
{
 
1066
  if (length &&
 
1067
      !is_keyword(name,length) &&
 
1068
      !require_quotes(name, length) &&
 
1069
      !(thd->options & OPTION_QUOTE_SHOW_CREATE))
 
1070
    return EOF;
 
1071
  if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
 
1072
    return '"';
 
1073
  return '`';
 
1074
}
 
1075
 
 
1076
 
 
1077
/* Append directory name (if exists) to CREATE INFO */
 
1078
 
 
1079
static void append_directory(THD *thd, String *packet, const char *dir_type,
 
1080
                             const char *filename)
 
1081
{
 
1082
  if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
 
1083
  {
 
1084
    uint length= dirname_length(filename);
 
1085
    packet->append(' ');
 
1086
    packet->append(dir_type);
 
1087
    packet->append(STRING_WITH_LEN(" DIRECTORY='"));
 
1088
#ifdef __WIN__
 
1089
    /* Convert \ to / to be able to create table on unix */
 
1090
    char *winfilename= (char*) thd->memdup(filename, length);
 
1091
    char *pos, *end;
 
1092
    for (pos= winfilename, end= pos+length ; pos < end ; pos++)
 
1093
    {
 
1094
      if (*pos == '\\')
 
1095
        *pos = '/';
 
1096
    }
 
1097
    filename= winfilename;
 
1098
#endif
 
1099
    packet->append(filename, length);
 
1100
    packet->append('\'');
 
1101
  }
 
1102
}
 
1103
 
 
1104
 
 
1105
#define LIST_PROCESS_HOST_LEN 64
 
1106
 
 
1107
static bool get_field_default_value(THD *thd, TABLE *table,
 
1108
                                    Field *field, String *def_value,
 
1109
                                    bool quoted)
 
1110
{
 
1111
  bool has_default;
 
1112
  bool has_now_default;
 
1113
  enum enum_field_types field_type= field->type();
 
1114
  /* 
 
1115
     We are using CURRENT_TIMESTAMP instead of NOW because it is
 
1116
     more standard
 
1117
  */
 
1118
  has_now_default= table->timestamp_field == field && 
 
1119
    field->unireg_check != Field::TIMESTAMP_UN_FIELD;
 
1120
    
 
1121
  has_default= (field_type != FIELD_TYPE_BLOB &&
 
1122
                !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
 
1123
                field->unireg_check != Field::NEXT_NUMBER &&
 
1124
                !((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
 
1125
                  && has_now_default));
 
1126
 
 
1127
  def_value->length(0);
 
1128
  if (has_default)
 
1129
  {
 
1130
    if (has_now_default)
 
1131
      def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
 
1132
    else if (!field->is_null())
 
1133
    {                                             // Not null by default
 
1134
      char tmp[MAX_FIELD_WIDTH];
 
1135
      String type(tmp, sizeof(tmp), field->charset());
 
1136
      if (field_type == MYSQL_TYPE_BIT)
 
1137
      {
 
1138
        longlong dec= field->val_int();
 
1139
        char *ptr= longlong2str(dec, tmp + 2, 2);
 
1140
        uint32 length= (uint32) (ptr - tmp);
 
1141
        tmp[0]= 'b';
 
1142
        tmp[1]= '\'';        
 
1143
        tmp[length]= '\'';
 
1144
        type.length(length + 1);
 
1145
        quoted= 0;
 
1146
      }
 
1147
      else
 
1148
        field->val_str(&type);
 
1149
      if (type.length())
 
1150
      {
 
1151
        String def_val;
 
1152
        uint dummy_errors;
 
1153
        /* convert to system_charset_info == utf8 */
 
1154
        def_val.copy(type.ptr(), type.length(), field->charset(),
 
1155
                     system_charset_info, &dummy_errors);
 
1156
        if (quoted)
 
1157
          append_unescaped(def_value, def_val.ptr(), def_val.length());
 
1158
        else
 
1159
          def_value->append(def_val.ptr(), def_val.length());
 
1160
      }
 
1161
      else if (quoted)
 
1162
        def_value->append(STRING_WITH_LEN("''"));
 
1163
    }
 
1164
    else if (field->maybe_null() && quoted)
 
1165
      def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
 
1166
    else
 
1167
      return 0;
 
1168
 
 
1169
  }
 
1170
  return has_default;
 
1171
}
 
1172
 
 
1173
/*
 
1174
  Build a CREATE TABLE statement for a table.
 
1175
 
 
1176
  SYNOPSIS
 
1177
    store_create_info()
 
1178
    thd               The thread
 
1179
    table_list        A list containing one table to write statement
 
1180
                      for.
 
1181
    packet            Pointer to a string where statement will be
 
1182
                      written.
 
1183
    create_info_arg   Pointer to create information that can be used
 
1184
                      to tailor the format of the statement.  Can be
 
1185
                      NULL, in which case only SQL_MODE is considered
 
1186
                      when building the statement.
 
1187
  
 
1188
  NOTE
 
1189
    Currently always return 0, but might return error code in the
 
1190
    future.
 
1191
    
 
1192
  RETURN
 
1193
    0       OK
 
1194
 */
 
1195
 
 
1196
int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
 
1197
                      HA_CREATE_INFO *create_info_arg, bool show_database)
 
1198
{
 
1199
  List<Item> field_list;
 
1200
  char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], def_value_buf[MAX_FIELD_WIDTH];
 
1201
  const char *alias;
 
1202
  String type(tmp, sizeof(tmp), system_charset_info);
 
1203
  String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
 
1204
  Field **ptr,*field;
 
1205
  uint primary_key;
 
1206
  KEY *key_info;
 
1207
  TABLE *table= table_list->table;
 
1208
  handler *file= table->file;
 
1209
  TABLE_SHARE *share= table->s;
 
1210
  HA_CREATE_INFO create_info;
 
1211
  bool show_table_options= FALSE;
 
1212
  bool foreign_db_mode=  (thd->variables.sql_mode & (MODE_POSTGRESQL |
 
1213
                                                     MODE_ORACLE |
 
1214
                                                     MODE_MSSQL |
 
1215
                                                     MODE_DB2 |
 
1216
                                                     MODE_MAXDB |
 
1217
                                                     MODE_ANSI)) != 0;
 
1218
  bool limited_mysql_mode= (thd->variables.sql_mode & (MODE_NO_FIELD_OPTIONS |
 
1219
                                                       MODE_MYSQL323 |
 
1220
                                                       MODE_MYSQL40)) != 0;
 
1221
  my_bitmap_map *old_map;
 
1222
  DBUG_ENTER("store_create_info");
 
1223
  DBUG_PRINT("enter",("table: %s", table->s->table_name.str));
 
1224
 
 
1225
  restore_record(table, s->default_values); // Get empty record
 
1226
 
 
1227
  if (share->tmp_table)
 
1228
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
 
1229
  else
 
1230
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
 
1231
  if (create_info_arg &&
 
1232
      (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
 
1233
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
1234
  if (table_list->schema_table)
 
1235
    alias= table_list->schema_table->table_name;
 
1236
  else
 
1237
  {
 
1238
    if (lower_case_table_names == 2)
 
1239
      alias= table->alias;
 
1240
    else
 
1241
    {
 
1242
      alias= share->table_name.str;
 
1243
    }
 
1244
  }
 
1245
 
 
1246
  /*
 
1247
    Print the database before the table name if told to do that. The
 
1248
    database name is only printed in the event that it is different
 
1249
    from the current database.  The main reason for doing this is to
 
1250
    avoid having to update gazillions of tests and result files, but
 
1251
    it also saves a few bytes of the binary log.
 
1252
   */
 
1253
  if (show_database)
 
1254
  {
 
1255
    const LEX_STRING *const db=
 
1256
      table_list->schema_table ? &INFORMATION_SCHEMA_NAME : &table->s->db;
 
1257
    if (!thd->db || strcmp(db->str, thd->db))
 
1258
    {
 
1259
      append_identifier(thd, packet, db->str, db->length);
 
1260
      packet->append(STRING_WITH_LEN("."));
 
1261
    }
 
1262
  }
 
1263
 
 
1264
  append_identifier(thd, packet, alias, strlen(alias));
 
1265
  packet->append(STRING_WITH_LEN(" (\n"));
 
1266
  /*
 
1267
    We need this to get default values from the table
 
1268
    We have to restore the read_set if we are called from insert in case
 
1269
    of row based replication.
 
1270
  */
 
1271
  old_map= tmp_use_all_columns(table, table->read_set);
 
1272
 
 
1273
  for (ptr=table->field ; (field= *ptr); ptr++)
 
1274
  {
 
1275
    uint flags = field->flags;
 
1276
 
 
1277
    if (ptr != table->field)
 
1278
      packet->append(STRING_WITH_LEN(",\n"));
 
1279
 
 
1280
    packet->append(STRING_WITH_LEN("  "));
 
1281
    append_identifier(thd,packet,field->field_name, strlen(field->field_name));
 
1282
    packet->append(' ');
 
1283
    // check for surprises from the previous call to Field::sql_type()
 
1284
    if (type.ptr() != tmp)
 
1285
      type.set(tmp, sizeof(tmp), system_charset_info);
 
1286
    else
 
1287
      type.set_charset(system_charset_info);
 
1288
 
 
1289
    field->sql_type(type);
 
1290
    packet->append(type.ptr(), type.length(), system_charset_info);
 
1291
 
 
1292
    if (field->has_charset() && 
 
1293
        !(thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)))
 
1294
    {
 
1295
      if (field->charset() != share->table_charset)
 
1296
      {
 
1297
        packet->append(STRING_WITH_LEN(" CHARACTER SET "));
 
1298
        packet->append(field->charset()->csname);
 
1299
      }
 
1300
      /* 
 
1301
        For string types dump collation name only if 
 
1302
        collation is not primary for the given charset
 
1303
      */
 
1304
      if (!(field->charset()->state & MY_CS_PRIMARY))
 
1305
      {
 
1306
        packet->append(STRING_WITH_LEN(" COLLATE "));
 
1307
        packet->append(field->charset()->name);
 
1308
      }
 
1309
    }
 
1310
 
 
1311
    if (flags & NOT_NULL_FLAG)
 
1312
      packet->append(STRING_WITH_LEN(" NOT NULL"));
 
1313
    else if (field->type() == MYSQL_TYPE_TIMESTAMP)
 
1314
    {
 
1315
      /*
 
1316
        TIMESTAMP field require explicit NULL flag, because unlike
 
1317
        all other fields they are treated as NOT NULL by default.
 
1318
      */
 
1319
      packet->append(STRING_WITH_LEN(" NULL"));
 
1320
    }
 
1321
 
 
1322
    if (get_field_default_value(thd, table, field, &def_value, 1))
 
1323
    {
 
1324
      packet->append(STRING_WITH_LEN(" DEFAULT "));
 
1325
      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
 
1326
    }
 
1327
 
 
1328
    if (!limited_mysql_mode && table->timestamp_field == field && 
 
1329
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
1330
      packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
 
1331
 
 
1332
    if (field->unireg_check == Field::NEXT_NUMBER && 
 
1333
        !(thd->variables.sql_mode & MODE_NO_FIELD_OPTIONS))
 
1334
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
 
1335
 
 
1336
    if (field->comment.length)
 
1337
    {
 
1338
      packet->append(STRING_WITH_LEN(" COMMENT "));
 
1339
      append_unescaped(packet, field->comment.str, field->comment.length);
 
1340
    }
 
1341
  }
 
1342
 
 
1343
  key_info= table->key_info;
 
1344
  bzero((char*) &create_info, sizeof(create_info));
 
1345
  /* Allow update_create_info to update row type */
 
1346
  create_info.row_type= share->row_type;
 
1347
  file->update_create_info(&create_info);
 
1348
  primary_key= share->primary_key;
 
1349
 
 
1350
  for (uint i=0 ; i < share->keys ; i++,key_info++)
 
1351
  {
 
1352
    KEY_PART_INFO *key_part= key_info->key_part;
 
1353
    bool found_primary=0;
 
1354
    packet->append(STRING_WITH_LEN(",\n  "));
 
1355
 
 
1356
    if (i == primary_key && !strcmp(key_info->name, primary_key_name))
 
1357
    {
 
1358
      found_primary=1;
 
1359
      /*
 
1360
        No space at end, because a space will be added after where the
 
1361
        identifier would go, but that is not added for primary key.
 
1362
      */
 
1363
      packet->append(STRING_WITH_LEN("PRIMARY KEY"));
 
1364
    }
 
1365
    else if (key_info->flags & HA_NOSAME)
 
1366
      packet->append(STRING_WITH_LEN("UNIQUE KEY "));
 
1367
    else if (key_info->flags & HA_FULLTEXT)
 
1368
      packet->append(STRING_WITH_LEN("FULLTEXT KEY "));
 
1369
    else if (key_info->flags & HA_SPATIAL)
 
1370
      packet->append(STRING_WITH_LEN("SPATIAL KEY "));
 
1371
    else
 
1372
      packet->append(STRING_WITH_LEN("KEY "));
 
1373
 
 
1374
    if (!found_primary)
 
1375
     append_identifier(thd, packet, key_info->name, strlen(key_info->name));
 
1376
 
 
1377
    packet->append(STRING_WITH_LEN(" ("));
 
1378
 
 
1379
    for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
 
1380
    {
 
1381
      if (j)
 
1382
        packet->append(',');
 
1383
 
 
1384
      if (key_part->field)
 
1385
        append_identifier(thd,packet,key_part->field->field_name,
 
1386
                          strlen(key_part->field->field_name));
 
1387
      if (key_part->field &&
 
1388
          (key_part->length !=
 
1389
           table->field[key_part->fieldnr-1]->key_length() &&
 
1390
           !(key_info->flags & (HA_FULLTEXT | HA_SPATIAL))))
 
1391
      {
 
1392
        char *end;
 
1393
        buff[0] = '(';
 
1394
        end= int10_to_str((long) key_part->length /
 
1395
                          key_part->field->charset()->mbmaxlen,
 
1396
                          buff + 1,10);
 
1397
        *end++ = ')';
 
1398
        packet->append(buff,(uint) (end-buff));
 
1399
      }
 
1400
    }
 
1401
    packet->append(')');
 
1402
    store_key_options(thd, packet, table, key_info);
 
1403
    if (key_info->parser)
 
1404
    {
 
1405
      LEX_STRING *parser_name= plugin_name(key_info->parser);
 
1406
      packet->append(STRING_WITH_LEN(" /*!50100 WITH PARSER "));
 
1407
      append_identifier(thd, packet, parser_name->str, parser_name->length);
 
1408
      packet->append(STRING_WITH_LEN(" */ "));
 
1409
    }
 
1410
  }
 
1411
 
 
1412
  /*
 
1413
    Get possible foreign key definitions stored in InnoDB and append them
 
1414
    to the CREATE TABLE statement
 
1415
  */
 
1416
 
 
1417
  if ((for_str= file->get_foreign_key_create_info()))
 
1418
  {
 
1419
    packet->append(for_str, strlen(for_str));
 
1420
    file->free_foreign_key_create_info(for_str);
 
1421
  }
 
1422
 
 
1423
  packet->append(STRING_WITH_LEN("\n)"));
 
1424
  if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
 
1425
  {
 
1426
    show_table_options= TRUE;
 
1427
    /*
 
1428
      Get possible table space definitions and append them
 
1429
      to the CREATE TABLE statement
 
1430
    */
 
1431
 
 
1432
    if ((for_str= file->get_tablespace_name(thd,0,0)))
 
1433
    {
 
1434
      packet->append(STRING_WITH_LEN(" /*!50100 TABLESPACE "));
 
1435
      packet->append(for_str, strlen(for_str));
 
1436
      packet->append(STRING_WITH_LEN(" STORAGE DISK */"));
 
1437
      my_free(for_str, MYF(0));
 
1438
    }
 
1439
 
 
1440
    /*
 
1441
      IF   check_create_info
 
1442
      THEN add ENGINE only if it was used when creating the table
 
1443
    */
 
1444
    if (!create_info_arg ||
 
1445
        (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
 
1446
    {
 
1447
      if (thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
 
1448
        packet->append(STRING_WITH_LEN(" TYPE="));
 
1449
      else
 
1450
        packet->append(STRING_WITH_LEN(" ENGINE="));
 
1451
#ifdef WITH_PARTITION_STORAGE_ENGINE
 
1452
    if (table->part_info)
 
1453
      packet->append(ha_resolve_storage_engine_name(
 
1454
                        table->part_info->default_engine_type));
 
1455
    else
 
1456
      packet->append(file->table_type());
 
1457
#else
 
1458
      packet->append(file->table_type());
 
1459
#endif
 
1460
    }
 
1461
 
 
1462
    /*
 
1463
      Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column,
 
1464
      and NEXT_ID > 1 (the default).  We must not print the clause
 
1465
      for engines that do not support this as it would break the
 
1466
      import of dumps, but as of this writing, the test for whether
 
1467
      AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=...
 
1468
      is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT))
 
1469
      Because of that, we do not explicitly test for the feature,
 
1470
      but may extrapolate its existence from that of an AUTO_INCREMENT column.
 
1471
    */
 
1472
 
 
1473
    if (create_info.auto_increment_value > 1)
 
1474
    {
 
1475
      char *end;
 
1476
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT="));
 
1477
      end= longlong10_to_str(create_info.auto_increment_value, buff,10);
 
1478
      packet->append(buff, (uint) (end - buff));
 
1479
    }
 
1480
 
 
1481
    
 
1482
    if (share->table_charset &&
 
1483
        !(thd->variables.sql_mode & MODE_MYSQL323) &&
 
1484
        !(thd->variables.sql_mode & MODE_MYSQL40))
 
1485
    {
 
1486
      /*
 
1487
        IF   check_create_info
 
1488
        THEN add DEFAULT CHARSET only if it was used when creating the table
 
1489
      */
 
1490
      if (!create_info_arg ||
 
1491
          (create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
1492
      {
 
1493
        packet->append(STRING_WITH_LEN(" DEFAULT CHARSET="));
 
1494
        packet->append(share->table_charset->csname);
 
1495
        if (!(share->table_charset->state & MY_CS_PRIMARY))
 
1496
        {
 
1497
          packet->append(STRING_WITH_LEN(" COLLATE="));
 
1498
          packet->append(table->s->table_charset->name);
 
1499
        }
 
1500
      }
 
1501
    }
 
1502
 
 
1503
    if (share->min_rows)
 
1504
    {
 
1505
      char *end;
 
1506
      packet->append(STRING_WITH_LEN(" MIN_ROWS="));
 
1507
      end= longlong10_to_str(share->min_rows, buff, 10);
 
1508
      packet->append(buff, (uint) (end- buff));
 
1509
    }
 
1510
 
 
1511
    if (share->max_rows && !table_list->schema_table)
 
1512
    {
 
1513
      char *end;
 
1514
      packet->append(STRING_WITH_LEN(" MAX_ROWS="));
 
1515
      end= longlong10_to_str(share->max_rows, buff, 10);
 
1516
      packet->append(buff, (uint) (end - buff));
 
1517
    }
 
1518
 
 
1519
    if (share->avg_row_length)
 
1520
    {
 
1521
      char *end;
 
1522
      packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH="));
 
1523
      end= longlong10_to_str(share->avg_row_length, buff,10);
 
1524
      packet->append(buff, (uint) (end - buff));
 
1525
    }
 
1526
 
 
1527
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
 
1528
      packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
 
1529
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
 
1530
      packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
 
1531
    /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
 
1532
    if (share->db_create_options & HA_OPTION_CHECKSUM)
 
1533
      packet->append(STRING_WITH_LEN(" CHECKSUM=1"));
 
1534
    if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
 
1535
      packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1"));
 
1536
    if (create_info.row_type != ROW_TYPE_DEFAULT)
 
1537
    {
 
1538
      packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
 
1539
      packet->append(ha_row_type[(uint) create_info.row_type]);
 
1540
    }
 
1541
    if (table->s->key_block_size)
 
1542
    {
 
1543
      char *end;
 
1544
      packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
1545
      end= longlong10_to_str(table->s->key_block_size, buff, 10);
 
1546
      packet->append(buff, (uint) (end - buff));
 
1547
    }
 
1548
    table->file->append_create_info(packet);
 
1549
    if (share->comment.length)
 
1550
    {
 
1551
      packet->append(STRING_WITH_LEN(" COMMENT="));
 
1552
      append_unescaped(packet, share->comment.str, share->comment.length);
 
1553
    }
 
1554
    if (share->connect_string.length)
 
1555
    {
 
1556
      packet->append(STRING_WITH_LEN(" CONNECTION="));
 
1557
      append_unescaped(packet, share->connect_string.str, share->connect_string.length);
 
1558
    }
 
1559
    append_directory(thd, packet, "DATA",  create_info.data_file_name);
 
1560
    append_directory(thd, packet, "INDEX", create_info.index_file_name);
 
1561
  }
 
1562
#ifdef WITH_PARTITION_STORAGE_ENGINE
 
1563
  {
 
1564
    /*
 
1565
      Partition syntax for CREATE TABLE is at the end of the syntax.
 
1566
    */
 
1567
    uint part_syntax_len;
 
1568
    char *part_syntax;
 
1569
    if (table->part_info &&
 
1570
        (!table->part_info->is_auto_partitioned) &&
 
1571
        ((part_syntax= generate_partition_syntax(table->part_info,
 
1572
                                                  &part_syntax_len,
 
1573
                                                  FALSE,
 
1574
                                                  show_table_options))))
 
1575
    {
 
1576
       packet->append(STRING_WITH_LEN("\n/*!50100"));
 
1577
       packet->append(part_syntax, part_syntax_len);
 
1578
       packet->append(STRING_WITH_LEN(" */"));
 
1579
       my_free(part_syntax, MYF(0));
 
1580
    }
 
1581
  }
 
1582
#endif
 
1583
  tmp_restore_column_map(table->read_set, old_map);
 
1584
  DBUG_RETURN(0);
 
1585
}
 
1586
 
 
1587
 
 
1588
static void store_key_options(THD *thd, String *packet, TABLE *table,
 
1589
                              KEY *key_info)
 
1590
{
 
1591
  bool limited_mysql_mode= (thd->variables.sql_mode &
 
1592
                            (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
 
1593
                             MODE_MYSQL40)) != 0;
 
1594
  bool foreign_db_mode=  (thd->variables.sql_mode & (MODE_POSTGRESQL |
 
1595
                                                     MODE_ORACLE |
 
1596
                                                     MODE_MSSQL |
 
1597
                                                     MODE_DB2 |
 
1598
                                                     MODE_MAXDB |
 
1599
                                                     MODE_ANSI)) != 0;
 
1600
  char *end, buff[32];
 
1601
 
 
1602
  if (!(thd->variables.sql_mode & MODE_NO_KEY_OPTIONS) &&
 
1603
      !limited_mysql_mode && !foreign_db_mode)
 
1604
  {
 
1605
 
 
1606
    if (key_info->algorithm == HA_KEY_ALG_BTREE)
 
1607
      packet->append(STRING_WITH_LEN(" USING BTREE"));
 
1608
 
 
1609
    if (key_info->algorithm == HA_KEY_ALG_HASH)
 
1610
      packet->append(STRING_WITH_LEN(" USING HASH"));
 
1611
 
 
1612
    /* send USING only in non-default case: non-spatial rtree */
 
1613
    if ((key_info->algorithm == HA_KEY_ALG_RTREE) &&
 
1614
        !(key_info->flags & HA_SPATIAL))
 
1615
      packet->append(STRING_WITH_LEN(" USING RTREE"));
 
1616
 
 
1617
    if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
 
1618
        table->s->key_block_size != key_info->block_size)
 
1619
    {
 
1620
      packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
1621
      end= longlong10_to_str(key_info->block_size, buff, 10);
 
1622
      packet->append(buff, (uint) (end - buff));
 
1623
    }
 
1624
  }
 
1625
}
 
1626
 
 
1627
 
 
1628
void
 
1629
view_store_options(THD *thd, TABLE_LIST *table, String *buff)
 
1630
{
 
1631
  append_algorithm(table, buff);
 
1632
  append_definer(thd, buff, &table->definer.user, &table->definer.host);
 
1633
  if (table->view_suid)
 
1634
    buff->append(STRING_WITH_LEN("SQL SECURITY DEFINER "));
 
1635
  else
 
1636
    buff->append(STRING_WITH_LEN("SQL SECURITY INVOKER "));
 
1637
}
 
1638
 
 
1639
 
 
1640
/*
 
1641
  Append DEFINER clause to the given buffer.
 
1642
  
 
1643
  SYNOPSIS
 
1644
    append_definer()
 
1645
    thd           [in] thread handle
 
1646
    buffer        [inout] buffer to hold DEFINER clause
 
1647
    definer_user  [in] user name part of definer
 
1648
    definer_host  [in] host name part of definer
 
1649
*/
 
1650
 
 
1651
static void append_algorithm(TABLE_LIST *table, String *buff)
 
1652
{
 
1653
  buff->append(STRING_WITH_LEN("ALGORITHM="));
 
1654
  switch ((int8)table->algorithm) {
 
1655
  case VIEW_ALGORITHM_UNDEFINED:
 
1656
    buff->append(STRING_WITH_LEN("UNDEFINED "));
 
1657
    break;
 
1658
  case VIEW_ALGORITHM_TMPTABLE:
 
1659
    buff->append(STRING_WITH_LEN("TEMPTABLE "));
 
1660
    break;
 
1661
  case VIEW_ALGORITHM_MERGE:
 
1662
    buff->append(STRING_WITH_LEN("MERGE "));
 
1663
    break;
 
1664
  default:
 
1665
    DBUG_ASSERT(0); // never should happen
 
1666
  }
 
1667
}
 
1668
 
 
1669
/*
 
1670
  Append DEFINER clause to the given buffer.
 
1671
  
 
1672
  SYNOPSIS
 
1673
    append_definer()
 
1674
    thd           [in] thread handle
 
1675
    buffer        [inout] buffer to hold DEFINER clause
 
1676
    definer_user  [in] user name part of definer
 
1677
    definer_host  [in] host name part of definer
 
1678
*/
 
1679
 
 
1680
void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
 
1681
                    const LEX_STRING *definer_host)
 
1682
{
 
1683
  buffer->append(STRING_WITH_LEN("DEFINER="));
 
1684
  append_identifier(thd, buffer, definer_user->str, definer_user->length);
 
1685
  buffer->append('@');
 
1686
  append_identifier(thd, buffer, definer_host->str, definer_host->length);
 
1687
  buffer->append(' ');
 
1688
}
 
1689
 
 
1690
 
 
1691
int
 
1692
view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
 
1693
{
 
1694
  my_bool compact_view_name= TRUE;
 
1695
  my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
 
1696
                                                       MODE_ORACLE |
 
1697
                                                       MODE_MSSQL |
 
1698
                                                       MODE_DB2 |
 
1699
                                                       MODE_MAXDB |
 
1700
                                                       MODE_ANSI)) != 0;
 
1701
 
 
1702
  if (!thd->db || strcmp(thd->db, table->view_db.str))
 
1703
    /*
 
1704
      print compact view name if the view belongs to the current database
 
1705
    */
 
1706
    compact_view_name= table->compact_view_format= FALSE;
 
1707
  else
 
1708
  {
 
1709
    /*
 
1710
      Compact output format for view body can be used
 
1711
      if this view only references table inside it's own db
 
1712
    */
 
1713
    TABLE_LIST *tbl;
 
1714
    table->compact_view_format= TRUE;
 
1715
    for (tbl= thd->lex->query_tables;
 
1716
         tbl;
 
1717
         tbl= tbl->next_global)
 
1718
    {
 
1719
      if (strcmp(table->view_db.str, tbl->view ? tbl->view_db.str :tbl->db)!= 0)
 
1720
      {
 
1721
        table->compact_view_format= FALSE;
 
1722
        break;
 
1723
      }
 
1724
    }
 
1725
  }
 
1726
 
 
1727
  buff->append(STRING_WITH_LEN("CREATE "));
 
1728
  if (!foreign_db_mode)
 
1729
  {
 
1730
    view_store_options(thd, table, buff);
 
1731
  }
 
1732
  buff->append(STRING_WITH_LEN("VIEW "));
 
1733
  if (!compact_view_name)
 
1734
  {
 
1735
    append_identifier(thd, buff, table->view_db.str, table->view_db.length);
 
1736
    buff->append('.');
 
1737
  }
 
1738
  append_identifier(thd, buff, table->view_name.str, table->view_name.length);
 
1739
  buff->append(STRING_WITH_LEN(" AS "));
 
1740
 
 
1741
  /*
 
1742
    We can't just use table->query, because our SQL_MODE may trigger
 
1743
    a different syntax, like when ANSI_QUOTES is defined.
 
1744
  */
 
1745
  table->view->unit.print(buff, QT_ORDINARY);
 
1746
 
 
1747
  if (table->with_check != VIEW_CHECK_NONE)
 
1748
  {
 
1749
    if (table->with_check == VIEW_CHECK_LOCAL)
 
1750
      buff->append(STRING_WITH_LEN(" WITH LOCAL CHECK OPTION"));
 
1751
    else
 
1752
      buff->append(STRING_WITH_LEN(" WITH CASCADED CHECK OPTION"));
 
1753
  }
 
1754
  return 0;
 
1755
}
 
1756
 
 
1757
 
 
1758
/****************************************************************************
 
1759
  Return info about all processes
 
1760
  returns for each thread: thread id, user, host, db, command, info
 
1761
****************************************************************************/
 
1762
 
 
1763
class thread_info :public ilink {
 
1764
public:
 
1765
  static void *operator new(size_t size)
 
1766
  {
 
1767
    return (void*) sql_alloc((uint) size);
 
1768
  }
 
1769
  static void operator delete(void *ptr __attribute__((unused)),
 
1770
                              size_t size __attribute__((unused)))
 
1771
  { TRASH(ptr, size); }
 
1772
 
 
1773
  ulong thread_id;
 
1774
  time_t start_time;
 
1775
  uint   command;
 
1776
  const char *user,*host,*db,*proc_info,*state_info;
 
1777
  char *query;
 
1778
};
 
1779
 
 
1780
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
1781
template class I_List<thread_info>;
 
1782
#endif
 
1783
 
 
1784
void mysqld_list_processes(THD *thd,const char *user, bool verbose)
 
1785
{
 
1786
  Item *field;
 
1787
  List<Item> field_list;
 
1788
  I_List<thread_info> thread_infos;
 
1789
  ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
 
1790
                           PROCESS_LIST_WIDTH);
 
1791
  Protocol *protocol= thd->protocol;
 
1792
  DBUG_ENTER("mysqld_list_processes");
 
1793
 
 
1794
  field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
1795
  field_list.push_back(new Item_empty_string("User",16));
 
1796
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
 
1797
  field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN));
 
1798
  field->maybe_null=1;
 
1799
  field_list.push_back(new Item_empty_string("Command",16));
 
1800
  field_list.push_back(field= new Item_return_int("Time",7, MYSQL_TYPE_LONG));
 
1801
  field->unsigned_flag= 0;
 
1802
  field_list.push_back(field=new Item_empty_string("State",30));
 
1803
  field->maybe_null=1;
 
1804
  field_list.push_back(field=new Item_empty_string("Info",max_query_length));
 
1805
  field->maybe_null=1;
 
1806
  if (protocol->send_fields(&field_list,
 
1807
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
1808
    DBUG_VOID_RETURN;
 
1809
 
 
1810
  VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
 
1811
  if (!thd->killed)
 
1812
  {
 
1813
    I_List_iterator<THD> it(threads);
 
1814
    THD *tmp;
 
1815
    while ((tmp=it++))
 
1816
    {
 
1817
      Security_context *tmp_sctx= tmp->security_ctx;
 
1818
      struct st_my_thread_var *mysys_var;
 
1819
      if ((tmp->vio_ok() || tmp->system_thread) &&
 
1820
          (!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user))))
 
1821
      {
 
1822
        thread_info *thd_info= new thread_info;
 
1823
 
 
1824
        thd_info->thread_id=tmp->thread_id;
 
1825
        thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user :
 
1826
                                    (tmp->system_thread ?
 
1827
                                     "system user" : "unauthenticated user"));
 
1828
        if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) &&
 
1829
            thd->security_ctx->host_or_ip[0])
 
1830
        {
 
1831
          if ((thd_info->host= (char*) thd->alloc(LIST_PROCESS_HOST_LEN+1)))
 
1832
            my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN,
 
1833
                        "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port);
 
1834
        }
 
1835
        else
 
1836
          thd_info->host= thd->strdup(tmp_sctx->host_or_ip[0] ? 
 
1837
                                      tmp_sctx->host_or_ip : 
 
1838
                                      tmp_sctx->host ? tmp_sctx->host : "");
 
1839
        if ((thd_info->db=tmp->db))             // Safe test
 
1840
          thd_info->db=thd->strdup(thd_info->db);
 
1841
        thd_info->command=(int) tmp->command;
 
1842
        if ((mysys_var= tmp->mysys_var))
 
1843
          pthread_mutex_lock(&mysys_var->mutex);
 
1844
        thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0);
 
1845
#ifndef EMBEDDED_LIBRARY
 
1846
        thd_info->state_info= (char*) (tmp->locked ? "Locked" :
 
1847
                                       tmp->net.reading_or_writing ?
 
1848
                                       (tmp->net.reading_or_writing == 2 ?
 
1849
                                        "Writing to net" :
 
1850
                                        thd_info->command == COM_SLEEP ? "" :
 
1851
                                        "Reading from net") :
 
1852
                                       tmp->proc_info ? tmp->proc_info :
 
1853
                                       tmp->mysys_var &&
 
1854
                                       tmp->mysys_var->current_cond ?
 
1855
                                       "Waiting on cond" : NullS);
 
1856
#else
 
1857
        thd_info->state_info= (char*)"Writing to net";
 
1858
#endif
 
1859
        if (mysys_var)
 
1860
          pthread_mutex_unlock(&mysys_var->mutex);
 
1861
 
 
1862
        thd_info->start_time= tmp->start_time;
 
1863
        thd_info->query=0;
 
1864
        /* Lock THD mutex that protects its data when looking at it. */
 
1865
        pthread_mutex_lock(&tmp->LOCK_thd_data);
 
1866
        if (tmp->query())
 
1867
        {
 
1868
          uint length= min(max_query_length, tmp->query_length());
 
1869
          thd_info->query= (char*) thd->strmake(tmp->query(),length);
 
1870
        }
 
1871
        pthread_mutex_unlock(&tmp->LOCK_thd_data);
 
1872
        thread_infos.append(thd_info);
 
1873
      }
 
1874
    }
 
1875
  }
 
1876
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
 
1877
 
 
1878
  thread_info *thd_info;
 
1879
  time_t now= my_time(0);
 
1880
  while ((thd_info=thread_infos.get()))
 
1881
  {
 
1882
    protocol->prepare_for_resend();
 
1883
    protocol->store((ulonglong) thd_info->thread_id);
 
1884
    protocol->store(thd_info->user, system_charset_info);
 
1885
    protocol->store(thd_info->host, system_charset_info);
 
1886
    protocol->store(thd_info->db, system_charset_info);
 
1887
    if (thd_info->proc_info)
 
1888
      protocol->store(thd_info->proc_info, system_charset_info);
 
1889
    else
 
1890
      protocol->store(command_name[thd_info->command].str, system_charset_info);
 
1891
    if (thd_info->start_time)
 
1892
      protocol->store_long ((longlong) (now - thd_info->start_time));
 
1893
    else
 
1894
      protocol->store_null();
 
1895
    protocol->store(thd_info->state_info, system_charset_info);
 
1896
    protocol->store(thd_info->query, system_charset_info);
 
1897
    if (protocol->write())
 
1898
      break; /* purecov: inspected */
 
1899
  }
 
1900
  my_eof(thd);
 
1901
  DBUG_VOID_RETURN;
 
1902
}
 
1903
 
 
1904
int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
 
1905
{
 
1906
  TABLE *table= tables->table;
 
1907
  CHARSET_INFO *cs= system_charset_info;
 
1908
  char *user;
 
1909
  time_t now= my_time(0);
 
1910
  DBUG_ENTER("fill_process_list");
 
1911
 
 
1912
  user= thd->security_ctx->master_access & PROCESS_ACL ?
 
1913
        NullS : thd->security_ctx->priv_user;
 
1914
 
 
1915
  VOID(pthread_mutex_lock(&LOCK_thread_count));
 
1916
 
 
1917
  if (!thd->killed)
 
1918
  {
 
1919
    I_List_iterator<THD> it(threads);
 
1920
    THD* tmp;
 
1921
 
 
1922
    while ((tmp= it++))
 
1923
    {
 
1924
      Security_context *tmp_sctx= tmp->security_ctx;
 
1925
      struct st_my_thread_var *mysys_var;
 
1926
      const char *val;
 
1927
 
 
1928
      if ((!tmp->vio_ok() && !tmp->system_thread) ||
 
1929
          (user && (!tmp_sctx->user || strcmp(tmp_sctx->user, user))))
 
1930
        continue;
 
1931
 
 
1932
      restore_record(table, s->default_values);
 
1933
      /* ID */
 
1934
      table->field[0]->store((longlong) tmp->thread_id, TRUE);
 
1935
      /* USER */
 
1936
      val= tmp_sctx->user ? tmp_sctx->user :
 
1937
            (tmp->system_thread ? "system user" : "unauthenticated user");
 
1938
      table->field[1]->store(val, strlen(val), cs);
 
1939
      /* HOST */
 
1940
      if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) &&
 
1941
          thd->security_ctx->host_or_ip[0])
 
1942
      {
 
1943
        char host[LIST_PROCESS_HOST_LEN + 1];
 
1944
        my_snprintf(host, LIST_PROCESS_HOST_LEN, "%s:%u",
 
1945
                    tmp_sctx->host_or_ip, tmp->peer_port);
 
1946
        table->field[2]->store(host, strlen(host), cs);
 
1947
      }
 
1948
      else
 
1949
        table->field[2]->store(tmp_sctx->host_or_ip,
 
1950
                               strlen(tmp_sctx->host_or_ip), cs);
 
1951
      /* DB */
 
1952
      if (tmp->db)
 
1953
      {
 
1954
        table->field[3]->store(tmp->db, strlen(tmp->db), cs);
 
1955
        table->field[3]->set_notnull();
 
1956
      }
 
1957
 
 
1958
      if ((mysys_var= tmp->mysys_var))
 
1959
        pthread_mutex_lock(&mysys_var->mutex);
 
1960
      /* COMMAND */
 
1961
      if ((val= (char *) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0)))
 
1962
        table->field[4]->store(val, strlen(val), cs);
 
1963
      else
 
1964
        table->field[4]->store(command_name[tmp->command].str,
 
1965
                               command_name[tmp->command].length, cs);
 
1966
      /* MYSQL_TIME */
 
1967
      table->field[5]->store((longlong)(tmp->start_time ?
 
1968
                                      now - tmp->start_time : 0), FALSE);
 
1969
      /* STATE */
 
1970
#ifndef EMBEDDED_LIBRARY
 
1971
      val= (char*) (tmp->locked ? "Locked" :
 
1972
                    tmp->net.reading_or_writing ?
 
1973
                    (tmp->net.reading_or_writing == 2 ?
 
1974
                     "Writing to net" :
 
1975
                     tmp->command == COM_SLEEP ? "" :
 
1976
                     "Reading from net") :
 
1977
                    tmp->proc_info ? tmp->proc_info :
 
1978
                    tmp->mysys_var &&
 
1979
                    tmp->mysys_var->current_cond ?
 
1980
                    "Waiting on cond" : NullS);
 
1981
#else
 
1982
      val= (char *) (tmp->proc_info ? tmp->proc_info : NullS);
 
1983
#endif
 
1984
      if (val)
 
1985
      {
 
1986
        table->field[6]->store(val, strlen(val), cs);
 
1987
        table->field[6]->set_notnull();
 
1988
      }
 
1989
 
 
1990
      if (mysys_var)
 
1991
        pthread_mutex_unlock(&mysys_var->mutex);
 
1992
 
 
1993
      /* INFO */
 
1994
      if (tmp->query())
 
1995
      {
 
1996
        table->field[7]->store(tmp->query(),
 
1997
                               min(PROCESS_LIST_INFO_WIDTH,
 
1998
                                   tmp->query_length()), cs);
 
1999
        table->field[7]->set_notnull();
 
2000
      }
 
2001
 
 
2002
      if (schema_table_store_record(thd, table))
 
2003
      {
 
2004
        VOID(pthread_mutex_unlock(&LOCK_thread_count));
 
2005
        DBUG_RETURN(1);
 
2006
      }
 
2007
    }
 
2008
  }
 
2009
 
 
2010
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
 
2011
  DBUG_RETURN(0);
 
2012
}
 
2013
 
 
2014
/*****************************************************************************
 
2015
  Status functions
 
2016
*****************************************************************************/
 
2017
 
 
2018
static DYNAMIC_ARRAY all_status_vars;
 
2019
static bool status_vars_inited= 0;
 
2020
static int show_var_cmp(const void *var1, const void *var2)
 
2021
{
 
2022
  return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
 
2023
}
 
2024
 
 
2025
/*
 
2026
  deletes all the SHOW_UNDEF elements from the array and calls
 
2027
  delete_dynamic() if it's completely empty.
 
2028
*/
 
2029
static void shrink_var_array(DYNAMIC_ARRAY *array)
 
2030
{
 
2031
  uint a,b;
 
2032
  SHOW_VAR *all= dynamic_element(array, 0, SHOW_VAR *);
 
2033
 
 
2034
  for (a= b= 0; b < array->elements; b++)
 
2035
    if (all[b].type != SHOW_UNDEF)
 
2036
      all[a++]= all[b];
 
2037
  if (a)
 
2038
  {
 
2039
    bzero(all+a, sizeof(SHOW_VAR)); // writing NULL-element to the end
 
2040
    array->elements= a;
 
2041
  }
 
2042
  else // array is completely empty - delete it
 
2043
    delete_dynamic(array);
 
2044
}
 
2045
 
 
2046
/*
 
2047
  Adds an array of SHOW_VAR entries to the output of SHOW STATUS
 
2048
 
 
2049
  SYNOPSIS
 
2050
    add_status_vars(SHOW_VAR *list)
 
2051
    list - an array of SHOW_VAR entries to add to all_status_vars
 
2052
           the last entry must be {0,0,SHOW_UNDEF}
 
2053
 
 
2054
  NOTE
 
2055
    The handling of all_status_vars[] is completely internal, it's allocated
 
2056
    automatically when something is added to it, and deleted completely when
 
2057
    the last entry is removed.
 
2058
 
 
2059
    As a special optimization, if add_status_vars() is called before
 
2060
    init_status_vars(), it assumes "startup mode" - neither concurrent access
 
2061
    to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
 
2062
 
 
2063
    The last entry of the all_status_vars[] should always be {0,0,SHOW_UNDEF}
 
2064
*/
 
2065
int add_status_vars(SHOW_VAR *list)
 
2066
{
 
2067
  int res= 0;
 
2068
  if (status_vars_inited)
 
2069
    pthread_mutex_lock(&LOCK_status);
 
2070
  if (!all_status_vars.buffer && // array is not allocated yet - do it now
 
2071
      my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20))
 
2072
  {
 
2073
    res= 1;
 
2074
    goto err;
 
2075
  }
 
2076
  while (list->name)
 
2077
    res|= insert_dynamic(&all_status_vars, (uchar*)list++);
 
2078
  res|= insert_dynamic(&all_status_vars, (uchar*)list); // appending NULL-element
 
2079
  all_status_vars.elements--; // but next insert_dynamic should overwite it
 
2080
  if (status_vars_inited)
 
2081
    sort_dynamic(&all_status_vars, show_var_cmp);
 
2082
err:
 
2083
  if (status_vars_inited)
 
2084
    pthread_mutex_unlock(&LOCK_status);
 
2085
  return res;
 
2086
}
 
2087
 
 
2088
/*
 
2089
  Make all_status_vars[] usable for SHOW STATUS
 
2090
 
 
2091
  NOTE
 
2092
    See add_status_vars(). Before init_status_vars() call, add_status_vars()
 
2093
    works in a special fast "startup" mode. Thus init_status_vars()
 
2094
    should be called as late as possible but before enabling multi-threading.
 
2095
*/
 
2096
void init_status_vars()
 
2097
{
 
2098
  status_vars_inited=1;
 
2099
  sort_dynamic(&all_status_vars, show_var_cmp);
 
2100
}
 
2101
 
 
2102
void reset_status_vars()
 
2103
{
 
2104
  SHOW_VAR *ptr= (SHOW_VAR*) all_status_vars.buffer;
 
2105
  SHOW_VAR *last= ptr + all_status_vars.elements;
 
2106
  for (; ptr < last; ptr++)
 
2107
  {
 
2108
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
2109
    if (ptr->type == SHOW_LONG)
 
2110
      *(ulong*) ptr->value= 0;
 
2111
  }  
 
2112
}
 
2113
 
 
2114
/*
 
2115
  catch-all cleanup function, cleans up everything no matter what
 
2116
 
 
2117
  DESCRIPTION
 
2118
    This function is not strictly required if all add_to_status/
 
2119
    remove_status_vars are properly paired, but it's a safety measure that
 
2120
    deletes everything from the all_status_vars[] even if some
 
2121
    remove_status_vars were forgotten
 
2122
*/
 
2123
void free_status_vars()
 
2124
{
 
2125
  delete_dynamic(&all_status_vars);
 
2126
}
 
2127
 
 
2128
/*
 
2129
  Removes an array of SHOW_VAR entries from the output of SHOW STATUS
 
2130
 
 
2131
  SYNOPSIS
 
2132
    remove_status_vars(SHOW_VAR *list)
 
2133
    list - an array of SHOW_VAR entries to remove to all_status_vars
 
2134
           the last entry must be {0,0,SHOW_UNDEF}
 
2135
 
 
2136
  NOTE
 
2137
    there's lots of room for optimizing this, especially in non-sorted mode,
 
2138
    but nobody cares - it may be called only in case of failed plugin
 
2139
    initialization in the mysqld startup.
 
2140
*/
 
2141
 
 
2142
void remove_status_vars(SHOW_VAR *list)
 
2143
{
 
2144
  if (status_vars_inited)
 
2145
  {
 
2146
    pthread_mutex_lock(&LOCK_status);
 
2147
    SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
 
2148
    int a= 0, b= all_status_vars.elements, c= (a+b)/2;
 
2149
 
 
2150
    for (; list->name; list++)
 
2151
    {
 
2152
      int res= 0;
 
2153
      for (a= 0, b= all_status_vars.elements; b-a > 1; c= (a+b)/2)
 
2154
      {
 
2155
        res= show_var_cmp(list, all+c);
 
2156
        if (res < 0)
 
2157
          b= c;
 
2158
        else if (res > 0)
 
2159
          a= c;
 
2160
        else
 
2161
          break;
 
2162
      }
 
2163
      if (res == 0)
 
2164
        all[c].type= SHOW_UNDEF;
 
2165
    }
 
2166
    shrink_var_array(&all_status_vars);
 
2167
    pthread_mutex_unlock(&LOCK_status);
 
2168
  }
 
2169
  else
 
2170
  {
 
2171
    SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
 
2172
    uint i;
 
2173
    for (; list->name; list++)
 
2174
    {
 
2175
      for (i= 0; i < all_status_vars.elements; i++)
 
2176
      {
 
2177
        if (show_var_cmp(list, all+i))
 
2178
          continue;
 
2179
        all[i].type= SHOW_UNDEF;
 
2180
        break;
 
2181
      }
 
2182
    }
 
2183
    shrink_var_array(&all_status_vars);
 
2184
  }
 
2185
}
 
2186
 
 
2187
inline void make_upper(char *buf)
 
2188
{
 
2189
  for (; *buf; buf++)
 
2190
    *buf= my_toupper(system_charset_info, *buf);
 
2191
}
 
2192
 
 
2193
static bool show_status_array(THD *thd, const char *wild,
 
2194
                              SHOW_VAR *variables,
 
2195
                              enum enum_var_type value_type,
 
2196
                              struct system_status_var *status_var,
 
2197
                              const char *prefix, TABLE *table,
 
2198
                              bool ucase_names,
 
2199
                              COND *cond)
 
2200
{
 
2201
  MY_ALIGNED_BYTE_ARRAY(buff_data, SHOW_VAR_FUNC_BUFF_SIZE, long);
 
2202
  char * const buff= (char *) &buff_data;
 
2203
  char *prefix_end;
 
2204
  /* the variable name should not be longer than 64 characters */
 
2205
  char name_buffer[64];
 
2206
  int len;
 
2207
  LEX_STRING null_lex_str;
 
2208
  SHOW_VAR tmp, *var;
 
2209
  COND *partial_cond= 0;
 
2210
  enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
 
2211
  bool res= FALSE;
 
2212
  CHARSET_INFO *charset= system_charset_info;
 
2213
  DBUG_ENTER("show_status_array");
 
2214
 
 
2215
  thd->count_cuted_fields= CHECK_FIELD_WARN;  
 
2216
  null_lex_str.str= 0;                          // For sys_var->value_ptr()
 
2217
  null_lex_str.length= 0;
 
2218
 
 
2219
  prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
 
2220
  if (*prefix)
 
2221
    *prefix_end++= '_';
 
2222
  len=name_buffer + sizeof(name_buffer) - prefix_end;
 
2223
  partial_cond= make_cond_for_info_schema(cond, table->pos_in_table_list);
 
2224
 
 
2225
  for (; variables->name; variables++)
 
2226
  {
 
2227
    strnmov(prefix_end, variables->name, len);
 
2228
    name_buffer[sizeof(name_buffer)-1]=0;       /* Safety */
 
2229
    if (ucase_names)
 
2230
      make_upper(name_buffer);
 
2231
 
 
2232
    restore_record(table, s->default_values);
 
2233
    table->field[0]->store(name_buffer, strlen(name_buffer),
 
2234
                           system_charset_info);
 
2235
    /*
 
2236
      if var->type is SHOW_FUNC, call the function.
 
2237
      Repeat as necessary, if new var is again SHOW_FUNC
 
2238
    */
 
2239
    for (var=variables; var->type == SHOW_FUNC; var= &tmp)
 
2240
      ((mysql_show_var_func)(var->value))(thd, &tmp, buff);
 
2241
 
 
2242
    SHOW_TYPE show_type=var->type;
 
2243
    if (show_type == SHOW_ARRAY)
 
2244
    {
 
2245
      show_status_array(thd, wild, (SHOW_VAR *) var->value, value_type,
 
2246
                        status_var, name_buffer, table, ucase_names, partial_cond);
 
2247
    }
 
2248
    else
 
2249
    {
 
2250
      if (!(wild && wild[0] && wild_case_compare(system_charset_info,
 
2251
                                                 name_buffer, wild)) &&
 
2252
          (!partial_cond || partial_cond->val_int()))
 
2253
      {
 
2254
        char *value=var->value;
 
2255
        const char *pos, *end;                  // We assign a lot of const's
 
2256
 
 
2257
        pthread_mutex_lock(&LOCK_global_system_variables);
 
2258
 
 
2259
        if (show_type == SHOW_SYS)
 
2260
        {
 
2261
          sys_var *var= ((sys_var *) value);
 
2262
          show_type= var->show_type();
 
2263
          value= (char*) var->value_ptr(thd, value_type, &null_lex_str);
 
2264
          charset= var->charset(thd);
 
2265
        }
 
2266
 
 
2267
        pos= end= buff;
 
2268
        /*
 
2269
          note that value may be == buff. All SHOW_xxx code below
 
2270
          should still work in this case
 
2271
        */
 
2272
        switch (show_type) {
 
2273
        case SHOW_DOUBLE_STATUS:
 
2274
          value= ((char *) status_var + (ulong) value);
 
2275
          /* fall through */
 
2276
        case SHOW_DOUBLE:
 
2277
          end= buff + my_sprintf(buff, (buff, "%f", *(double*) value));
 
2278
          break;
 
2279
        case SHOW_LONG_STATUS:
 
2280
          value= ((char *) status_var + (ulong) value);
 
2281
          /* fall through */
 
2282
        case SHOW_LONG:
 
2283
        case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
 
2284
          end= int10_to_str(*(long*) value, buff, 10);
 
2285
          break;
 
2286
        case SHOW_LONGLONG_STATUS:
 
2287
          value= ((char *) status_var + (ulonglong) value);
 
2288
          /* fall through */
 
2289
        case SHOW_LONGLONG:
 
2290
          end= longlong10_to_str(*(longlong*) value, buff, 10);
 
2291
          break;
 
2292
        case SHOW_HA_ROWS:
 
2293
          end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
 
2294
          break;
 
2295
        case SHOW_BOOL:
 
2296
          end= strmov(buff, *(bool*) value ? "ON" : "OFF");
 
2297
          break;
 
2298
        case SHOW_MY_BOOL:
 
2299
          end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
 
2300
          break;
 
2301
        case SHOW_INT:
 
2302
          end= int10_to_str((long) *(uint32*) value, buff, 10);
 
2303
          break;
 
2304
        case SHOW_HAVE:
 
2305
        {
 
2306
          SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
 
2307
          pos= show_comp_option_name[(int) tmp];
 
2308
          end= strend(pos);
 
2309
          break;
 
2310
        }
 
2311
        case SHOW_CHAR:
 
2312
        {
 
2313
          if (!(pos= value))
 
2314
            pos= "";
 
2315
          end= strend(pos);
 
2316
          break;
 
2317
        }
 
2318
       case SHOW_CHAR_PTR:
 
2319
        {
 
2320
          if (!(pos= *(char**) value))
 
2321
            pos= "";
 
2322
          end= strend(pos);
 
2323
          break;
 
2324
        }
 
2325
        case SHOW_KEY_CACHE_LONG:
 
2326
          value= (char*) dflt_key_cache + (ulong)value;
 
2327
          end= int10_to_str(*(long*) value, buff, 10);
 
2328
          break;
 
2329
        case SHOW_KEY_CACHE_LONGLONG:
 
2330
          value= (char*) dflt_key_cache + (ulong)value;
 
2331
          end= longlong10_to_str(*(longlong*) value, buff, 10);
 
2332
          break;
 
2333
        case SHOW_UNDEF:
 
2334
          break;                                        // Return empty string
 
2335
        case SHOW_SYS:                                  // Cannot happen
 
2336
        default:
 
2337
          DBUG_ASSERT(0);
 
2338
          break;
 
2339
        }
 
2340
        table->field[1]->store(pos, (uint32) (end - pos), charset);
 
2341
        thd->count_cuted_fields= CHECK_FIELD_IGNORE;
 
2342
        table->field[1]->set_notnull();
 
2343
 
 
2344
        pthread_mutex_unlock(&LOCK_global_system_variables);
 
2345
 
 
2346
        if (schema_table_store_record(thd, table))
 
2347
        {
 
2348
          res= TRUE;
 
2349
          goto end;
 
2350
        }
 
2351
      }
 
2352
    }
 
2353
  }
 
2354
end:
 
2355
  thd->count_cuted_fields= save_count_cuted_fields;
 
2356
  DBUG_RETURN(res);
 
2357
}
 
2358
 
 
2359
 
 
2360
/* collect status for all running threads */
 
2361
 
 
2362
void calc_sum_of_all_status(STATUS_VAR *to)
 
2363
{
 
2364
  DBUG_ENTER("calc_sum_of_all_status");
 
2365
 
 
2366
  /* Ensure that thread id not killed during loop */
 
2367
  VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
 
2368
 
 
2369
  I_List_iterator<THD> it(threads);
 
2370
  THD *tmp;
 
2371
  
 
2372
  /* Get global values as base */
 
2373
  *to= global_status_var;
 
2374
  
 
2375
  /* Add to this status from existing threads */
 
2376
  while ((tmp= it++))
 
2377
    add_to_status(to, &tmp->status_var);
 
2378
  
 
2379
  VOID(pthread_mutex_unlock(&LOCK_thread_count));
 
2380
  DBUG_VOID_RETURN;
 
2381
}
 
2382
 
 
2383
 
 
2384
/* This is only used internally, but we need it here as a forward reference */
 
2385
extern ST_SCHEMA_TABLE schema_tables[];
 
2386
 
 
2387
typedef struct st_lookup_field_values
 
2388
{
 
2389
  LEX_STRING db_value, table_value;
 
2390
  bool wild_db_value, wild_table_value;
 
2391
} LOOKUP_FIELD_VALUES;
 
2392
 
 
2393
 
 
2394
/*
 
2395
  Store record to I_S table, convert HEAP table
 
2396
  to MyISAM if necessary
 
2397
 
 
2398
  SYNOPSIS
 
2399
    schema_table_store_record()
 
2400
    thd                   thread handler
 
2401
    table                 Information schema table to be updated
 
2402
 
 
2403
  RETURN
 
2404
    0                     success
 
2405
    1                     error
 
2406
*/
 
2407
 
 
2408
bool schema_table_store_record(THD *thd, TABLE *table)
 
2409
{
 
2410
  int error;
 
2411
  if ((error= table->file->ha_write_row(table->record[0])))
 
2412
  {
 
2413
    if (create_myisam_from_heap(thd, table, 
 
2414
                                table->pos_in_table_list->schema_table_param,
 
2415
                                error, 0))
 
2416
      return 1;
 
2417
  }
 
2418
  return 0;
 
2419
}
 
2420
 
 
2421
 
 
2422
int make_table_list(THD *thd, SELECT_LEX *sel,
 
2423
                    LEX_STRING *db_name, LEX_STRING *table_name)
 
2424
{
 
2425
  Table_ident *table_ident;
 
2426
  table_ident= new Table_ident(thd, *db_name, *table_name, 1);
 
2427
  sel->init_query();
 
2428
  if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ))
 
2429
    return 1;
 
2430
  return 0;
 
2431
}
 
2432
 
 
2433
 
 
2434
/**
 
2435
  @brief    Get lookup value from the part of 'WHERE' condition 
 
2436
 
 
2437
  @details This function gets lookup value from 
 
2438
           the part of 'WHERE' condition if it's possible and 
 
2439
           fill appropriate lookup_field_vals struct field
 
2440
           with this value.
 
2441
 
 
2442
  @param[in]      thd                   thread handler
 
2443
  @param[in]      item_func             part of WHERE condition
 
2444
  @param[in]      table                 I_S table
 
2445
  @param[in, out] lookup_field_vals     Struct which holds lookup values 
 
2446
 
 
2447
  @return
 
2448
    0             success
 
2449
    1             error, there can be no matching records for the condition
 
2450
*/
 
2451
 
 
2452
bool get_lookup_value(THD *thd, Item_func *item_func,
 
2453
                      TABLE_LIST *table, 
 
2454
                      LOOKUP_FIELD_VALUES *lookup_field_vals)
 
2455
{
 
2456
  ST_SCHEMA_TABLE *schema_table= table->schema_table;
 
2457
  ST_FIELD_INFO *field_info= schema_table->fields_info;
 
2458
  const char *field_name1= schema_table->idx_field1 >= 0 ?
 
2459
    field_info[schema_table->idx_field1].field_name : "";
 
2460
  const char *field_name2= schema_table->idx_field2 >= 0 ?
 
2461
    field_info[schema_table->idx_field2].field_name : "";
 
2462
 
 
2463
  if (item_func->functype() == Item_func::EQ_FUNC ||
 
2464
      item_func->functype() == Item_func::EQUAL_FUNC)
 
2465
  {
 
2466
    int idx_field, idx_val;
 
2467
    char tmp[MAX_FIELD_WIDTH];
 
2468
    String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info);
 
2469
    Item_field *item_field;
 
2470
    CHARSET_INFO *cs= system_charset_info;
 
2471
 
 
2472
    if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
 
2473
        item_func->arguments()[1]->const_item())
 
2474
    {
 
2475
      idx_field= 0;
 
2476
      idx_val= 1;
 
2477
    }
 
2478
    else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
 
2479
             item_func->arguments()[0]->const_item())
 
2480
    {
 
2481
      idx_field= 1;
 
2482
      idx_val= 0;
 
2483
    }
 
2484
    else
 
2485
      return 0;
 
2486
 
 
2487
    item_field= (Item_field*) item_func->arguments()[idx_field];
 
2488
    if (table->table != item_field->field->table)
 
2489
      return 0;
 
2490
    tmp_str= item_func->arguments()[idx_val]->val_str(&str_buff);
 
2491
 
 
2492
    /* impossible value */
 
2493
    if (!tmp_str)
 
2494
      return 1;
 
2495
 
 
2496
    /* Lookup value is database name */
 
2497
    if (!cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
 
2498
                               (uchar *) item_field->field_name,
 
2499
                               strlen(item_field->field_name), 0))
 
2500
    {
 
2501
      thd->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(),
 
2502
                           tmp_str->length(), FALSE);
 
2503
    }
 
2504
    /* Lookup value is table name */
 
2505
    else if (!cs->coll->strnncollsp(cs, (uchar *) field_name2,
 
2506
                                    strlen(field_name2),
 
2507
                                    (uchar *) item_field->field_name,
 
2508
                                    strlen(item_field->field_name), 0))
 
2509
    {
 
2510
      thd->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(),
 
2511
                           tmp_str->length(), FALSE);
 
2512
    }
 
2513
  }
 
2514
  return 0;
 
2515
}
 
2516
 
 
2517
 
 
2518
/**
 
2519
  @brief    Calculates lookup values from 'WHERE' condition 
 
2520
 
 
2521
  @details This function calculates lookup value(database name, table name)
 
2522
           from 'WHERE' condition if it's possible and 
 
2523
           fill lookup_field_vals struct fields with these values.
 
2524
 
 
2525
  @param[in]      thd                   thread handler
 
2526
  @param[in]      cond                  WHERE condition
 
2527
  @param[in]      table                 I_S table
 
2528
  @param[in, out] lookup_field_vals     Struct which holds lookup values 
 
2529
 
 
2530
  @return
 
2531
    0             success
 
2532
    1             error, there can be no matching records for the condition
 
2533
*/
 
2534
 
 
2535
bool calc_lookup_values_from_cond(THD *thd, COND *cond, TABLE_LIST *table,
 
2536
                                  LOOKUP_FIELD_VALUES *lookup_field_vals)
 
2537
{
 
2538
  if (!cond)
 
2539
    return 0;
 
2540
 
 
2541
  if (cond->type() == Item::COND_ITEM)
 
2542
  {
 
2543
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
 
2544
    {
 
2545
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
2546
      Item *item;
 
2547
      while ((item= li++))
 
2548
      {
 
2549
        if (item->type() == Item::FUNC_ITEM)
 
2550
        {
 
2551
          if (get_lookup_value(thd, (Item_func*)item, table, lookup_field_vals))
 
2552
            return 1;
 
2553
        }
 
2554
        else
 
2555
        {
 
2556
          if (calc_lookup_values_from_cond(thd, item, table, lookup_field_vals))
 
2557
            return 1;
 
2558
        }
 
2559
      }
 
2560
    }
 
2561
    return 0;
 
2562
  }
 
2563
  else if (cond->type() == Item::FUNC_ITEM &&
 
2564
           get_lookup_value(thd, (Item_func*) cond, table, lookup_field_vals))
 
2565
    return 1;
 
2566
  return 0;
 
2567
}
 
2568
 
 
2569
 
 
2570
bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
 
2571
{
 
2572
  if (item->type() == Item::FUNC_ITEM)
 
2573
  {
 
2574
    Item_func *item_func= (Item_func*)item;
 
2575
    for (uint i=0; i<item_func->argument_count(); i++)
 
2576
    {
 
2577
      if (!uses_only_table_name_fields(item_func->arguments()[i], table))
 
2578
        return 0;
 
2579
    }
 
2580
  }
 
2581
  else if (item->type() == Item::FIELD_ITEM)
 
2582
  {
 
2583
    Item_field *item_field= (Item_field*)item;
 
2584
    CHARSET_INFO *cs= system_charset_info;
 
2585
    ST_SCHEMA_TABLE *schema_table= table->schema_table;
 
2586
    ST_FIELD_INFO *field_info= schema_table->fields_info;
 
2587
    const char *field_name1= schema_table->idx_field1 >= 0 ?
 
2588
      field_info[schema_table->idx_field1].field_name : "";
 
2589
    const char *field_name2= schema_table->idx_field2 >= 0 ?
 
2590
      field_info[schema_table->idx_field2].field_name : "";
 
2591
    if (table->table != item_field->field->table ||
 
2592
        (cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1),
 
2593
                               (uchar *) item_field->field_name,
 
2594
                               strlen(item_field->field_name), 0) &&
 
2595
         cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2),
 
2596
                               (uchar *) item_field->field_name,
 
2597
                               strlen(item_field->field_name), 0)))
 
2598
      return 0;
 
2599
  }
 
2600
  else if (item->type() == Item::REF_ITEM)
 
2601
    return uses_only_table_name_fields(item->real_item(), table);
 
2602
 
 
2603
  if (item->type() == Item::SUBSELECT_ITEM && !item->const_item())
 
2604
    return 0;
 
2605
 
 
2606
  return 1;
 
2607
}
 
2608
 
 
2609
 
 
2610
static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table)
 
2611
{
 
2612
  if (!cond)
 
2613
    return (COND*) 0;
 
2614
  if (cond->type() == Item::COND_ITEM)
 
2615
  {
 
2616
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
 
2617
    {
 
2618
      /* Create new top level AND item */
 
2619
      Item_cond_and *new_cond=new Item_cond_and;
 
2620
      if (!new_cond)
 
2621
        return (COND*) 0;
 
2622
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
2623
      Item *item;
 
2624
      while ((item=li++))
 
2625
      {
 
2626
        Item *fix= make_cond_for_info_schema(item, table);
 
2627
        if (fix)
 
2628
          new_cond->argument_list()->push_back(fix);
 
2629
      }
 
2630
      switch (new_cond->argument_list()->elements) {
 
2631
      case 0:
 
2632
        return (COND*) 0;
 
2633
      case 1:
 
2634
        return new_cond->argument_list()->head();
 
2635
      default:
 
2636
        new_cond->quick_fix_field();
 
2637
        return new_cond;
 
2638
      }
 
2639
    }
 
2640
    else
 
2641
    {                                           // Or list
 
2642
      Item_cond_or *new_cond=new Item_cond_or;
 
2643
      if (!new_cond)
 
2644
        return (COND*) 0;
 
2645
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
2646
      Item *item;
 
2647
      while ((item=li++))
 
2648
      {
 
2649
        Item *fix=make_cond_for_info_schema(item, table);
 
2650
        if (!fix)
 
2651
          return (COND*) 0;
 
2652
        new_cond->argument_list()->push_back(fix);
 
2653
      }
 
2654
      new_cond->quick_fix_field();
 
2655
      new_cond->top_level_item();
 
2656
      return new_cond;
 
2657
    }
 
2658
  }
 
2659
 
 
2660
  if (!uses_only_table_name_fields(cond, table))
 
2661
    return (COND*) 0;
 
2662
  return cond;
 
2663
}
 
2664
 
 
2665
 
 
2666
/**
 
2667
  @brief   Calculate lookup values(database name, table name)
 
2668
 
 
2669
  @details This function calculates lookup values(database name, table name)
 
2670
           from 'WHERE' condition or wild values (for 'SHOW' commands only)
 
2671
           from LEX struct and fill lookup_field_vals struct field
 
2672
           with these values.
 
2673
 
 
2674
  @param[in]      thd                   thread handler
 
2675
  @param[in]      cond                  WHERE condition
 
2676
  @param[in]      tables                I_S table
 
2677
  @param[in, out] lookup_field_values   Struct which holds lookup values 
 
2678
 
 
2679
  @return
 
2680
    0             success
 
2681
    1             error, there can be no matching records for the condition
 
2682
*/
 
2683
 
 
2684
bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables,
 
2685
                             LOOKUP_FIELD_VALUES *lookup_field_values)
 
2686
{
 
2687
  LEX *lex= thd->lex;
 
2688
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
 
2689
  bzero((char*) lookup_field_values, sizeof(LOOKUP_FIELD_VALUES));
 
2690
  switch (lex->sql_command) {
 
2691
  case SQLCOM_SHOW_DATABASES:
 
2692
    if (wild)
 
2693
    {
 
2694
      lookup_field_values->db_value.str= (char*) wild;
 
2695
      lookup_field_values->db_value.length= strlen(wild);
 
2696
      lookup_field_values->wild_db_value= 1;
 
2697
    }
 
2698
    return 0;
 
2699
  case SQLCOM_SHOW_TABLES:
 
2700
  case SQLCOM_SHOW_TABLE_STATUS:
 
2701
  case SQLCOM_SHOW_TRIGGERS:
 
2702
  case SQLCOM_SHOW_EVENTS:
 
2703
    lookup_field_values->db_value.str= lex->select_lex.db;
 
2704
    lookup_field_values->db_value.length=strlen(lex->select_lex.db);
 
2705
    if (wild)
 
2706
    {
 
2707
      lookup_field_values->table_value.str= (char*)wild;
 
2708
      lookup_field_values->table_value.length= strlen(wild);
 
2709
      lookup_field_values->wild_table_value= 1;
 
2710
    }
 
2711
    return 0;
 
2712
  default:
 
2713
    /*
 
2714
      The "default" is for queries over I_S.
 
2715
      All previous cases handle SHOW commands.
 
2716
    */
 
2717
    return calc_lookup_values_from_cond(thd, cond, tables, lookup_field_values);
 
2718
  }
 
2719
}
 
2720
 
 
2721
 
 
2722
enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table)
 
2723
{
 
2724
  return (enum enum_schema_tables) (schema_table - &schema_tables[0]);
 
2725
}
 
2726
 
 
2727
 
 
2728
/*
 
2729
  Create db names list. Information schema name always is first in list
 
2730
 
 
2731
  SYNOPSIS
 
2732
    make_db_list()
 
2733
    thd                   thread handler
 
2734
    files                 list of db names
 
2735
    wild                  wild string
 
2736
    idx_field_vals        idx_field_vals->db_name contains db name or
 
2737
                          wild string
 
2738
    with_i_schema         returns 1 if we added 'IS' name to list
 
2739
                          otherwise returns 0 
 
2740
 
 
2741
  RETURN
 
2742
    zero                  success
 
2743
    non-zero              error
 
2744
*/
 
2745
 
 
2746
int make_db_list(THD *thd, List<LEX_STRING> *files,
 
2747
                 LOOKUP_FIELD_VALUES *lookup_field_vals,
 
2748
                 bool *with_i_schema)
 
2749
{
 
2750
  LEX_STRING *i_s_name_copy= 0;
 
2751
  i_s_name_copy= thd->make_lex_string(i_s_name_copy,
 
2752
                                      INFORMATION_SCHEMA_NAME.str,
 
2753
                                      INFORMATION_SCHEMA_NAME.length, TRUE);
 
2754
  *with_i_schema= 0;
 
2755
  if (lookup_field_vals->wild_db_value)
 
2756
  {
 
2757
    /*
 
2758
      This part of code is only for SHOW DATABASES command.
 
2759
      idx_field_vals->db_value can be 0 when we don't use
 
2760
      LIKE clause (see also get_index_field_values() function)
 
2761
    */
 
2762
    if (!lookup_field_vals->db_value.str ||
 
2763
        !wild_case_compare(system_charset_info, 
 
2764
                           INFORMATION_SCHEMA_NAME.str,
 
2765
                           lookup_field_vals->db_value.str))
 
2766
    {
 
2767
      *with_i_schema= 1;
 
2768
      if (files->push_back(i_s_name_copy))
 
2769
        return 1;
 
2770
    }
 
2771
    return (find_files(thd, files, NullS, mysql_data_home,
 
2772
                       lookup_field_vals->db_value.str, 1) != FIND_FILES_OK);
 
2773
  }
 
2774
 
 
2775
 
 
2776
  /*
 
2777
    If we have db lookup vaule we just add it to list and
 
2778
    exit from the function
 
2779
  */
 
2780
  if (lookup_field_vals->db_value.str)
 
2781
  {
 
2782
    if (is_schema_db(lookup_field_vals->db_value.str, 
 
2783
                     lookup_field_vals->db_value.length))
 
2784
    {
 
2785
      *with_i_schema= 1;
 
2786
      if (files->push_back(i_s_name_copy))
 
2787
        return 1;
 
2788
      return 0;
 
2789
    }
 
2790
    if (files->push_back(&lookup_field_vals->db_value))
 
2791
      return 1;
 
2792
    return 0;
 
2793
  }
 
2794
 
 
2795
  /*
 
2796
    Create list of existing databases. It is used in case
 
2797
    of select from information schema table
 
2798
  */
 
2799
  if (files->push_back(i_s_name_copy))
 
2800
    return 1;
 
2801
  *with_i_schema= 1;
 
2802
  return (find_files(thd, files, NullS,
 
2803
                     mysql_data_home, NullS, 1) != FIND_FILES_OK);
 
2804
}
 
2805
 
 
2806
 
 
2807
struct st_add_schema_table 
 
2808
{
 
2809
  List<LEX_STRING> *files;
 
2810
  const char *wild;
 
2811
};
 
2812
 
 
2813
 
 
2814
static my_bool add_schema_table(THD *thd, plugin_ref plugin,
 
2815
                                void* p_data)
 
2816
{
 
2817
  LEX_STRING *file_name= 0;
 
2818
  st_add_schema_table *data= (st_add_schema_table *)p_data;
 
2819
  List<LEX_STRING> *file_list= data->files;
 
2820
  const char *wild= data->wild;
 
2821
  ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
 
2822
  DBUG_ENTER("add_schema_table");
 
2823
 
 
2824
  if (schema_table->hidden)
 
2825
      DBUG_RETURN(0);
 
2826
  if (wild)
 
2827
  {
 
2828
    if (lower_case_table_names)
 
2829
    {
 
2830
      if (wild_case_compare(files_charset_info,
 
2831
                            schema_table->table_name,
 
2832
                            wild))
 
2833
        DBUG_RETURN(0);
 
2834
    }
 
2835
    else if (wild_compare(schema_table->table_name, wild, 0))
 
2836
      DBUG_RETURN(0);
 
2837
  }
 
2838
 
 
2839
  if ((file_name= thd->make_lex_string(file_name, schema_table->table_name,
 
2840
                                       strlen(schema_table->table_name),
 
2841
                                       TRUE)) &&
 
2842
      !file_list->push_back(file_name))
 
2843
    DBUG_RETURN(0);
 
2844
  DBUG_RETURN(1);
 
2845
}
 
2846
 
 
2847
 
 
2848
int schema_tables_add(THD *thd, List<LEX_STRING> *files, const char *wild)
 
2849
{
 
2850
  LEX_STRING *file_name= 0;
 
2851
  ST_SCHEMA_TABLE *tmp_schema_table= schema_tables;
 
2852
  st_add_schema_table add_data;
 
2853
  DBUG_ENTER("schema_tables_add");
 
2854
 
 
2855
  for (; tmp_schema_table->table_name; tmp_schema_table++)
 
2856
  {
 
2857
    if (tmp_schema_table->hidden)
 
2858
      continue;
 
2859
    if (wild)
 
2860
    {
 
2861
      if (lower_case_table_names)
 
2862
      {
 
2863
        if (wild_case_compare(files_charset_info,
 
2864
                              tmp_schema_table->table_name,
 
2865
                              wild))
 
2866
          continue;
 
2867
      }
 
2868
      else if (wild_compare(tmp_schema_table->table_name, wild, 0))
 
2869
        continue;
 
2870
    }
 
2871
    if ((file_name= 
 
2872
         thd->make_lex_string(file_name, tmp_schema_table->table_name,
 
2873
                              strlen(tmp_schema_table->table_name), TRUE)) &&
 
2874
        !files->push_back(file_name))
 
2875
      continue;
 
2876
    DBUG_RETURN(1);
 
2877
  }
 
2878
 
 
2879
  add_data.files= files;
 
2880
  add_data.wild= wild;
 
2881
  if (plugin_foreach(thd, add_schema_table,
 
2882
                     MYSQL_INFORMATION_SCHEMA_PLUGIN, &add_data))
 
2883
      DBUG_RETURN(1);
 
2884
 
 
2885
  DBUG_RETURN(0);
 
2886
}
 
2887
 
 
2888
 
 
2889
/**
 
2890
  @brief          Create table names list
 
2891
 
 
2892
  @details        The function creates the list of table names in
 
2893
                  database
 
2894
 
 
2895
  @param[in]      thd                   thread handler
 
2896
  @param[in]      table_names           List of table names in database
 
2897
  @param[in]      lex                   pointer to LEX struct
 
2898
  @param[in]      lookup_field_vals     pointer to LOOKUP_FIELD_VALUE struct
 
2899
  @param[in]      with_i_schema         TRUE means that we add I_S tables to list
 
2900
  @param[in]      db_name               database name
 
2901
 
 
2902
  @return         Operation status
 
2903
    @retval       0           ok
 
2904
    @retval       1           fatal error
 
2905
    @retval       2           Not fatal error; Safe to ignore this file list
 
2906
*/
 
2907
 
 
2908
static int
 
2909
make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
 
2910
                     LOOKUP_FIELD_VALUES *lookup_field_vals,
 
2911
                     bool with_i_schema, LEX_STRING *db_name)
 
2912
{
 
2913
  char path[FN_REFLEN + 1];
 
2914
  build_table_filename(path, sizeof(path) - 1, db_name->str, "", "", 0);
 
2915
  if (!lookup_field_vals->wild_table_value &&
 
2916
      lookup_field_vals->table_value.str)
 
2917
  {
 
2918
    if (with_i_schema)
 
2919
    {
 
2920
      if (find_schema_table(thd, lookup_field_vals->table_value.str))
 
2921
      {
 
2922
        if (table_names->push_back(&lookup_field_vals->table_value))
 
2923
          return 1;
 
2924
      }
 
2925
    }
 
2926
    else
 
2927
    {    
 
2928
      if (table_names->push_back(&lookup_field_vals->table_value))
 
2929
        return 1;
 
2930
      /*
 
2931
        Check that table is relevant in current transaction.
 
2932
        (used for ndb engine, see ndbcluster_find_files(), ha_ndbcluster.cc)
 
2933
      */
 
2934
      VOID(ha_find_files(thd, db_name->str, path,
 
2935
                         lookup_field_vals->table_value.str, 0,
 
2936
                         table_names));
 
2937
    }
 
2938
    return 0;
 
2939
  }
 
2940
 
 
2941
  /*
 
2942
    This call will add all matching the wildcards (if specified) IS tables
 
2943
    to the list
 
2944
  */
 
2945
  if (with_i_schema)
 
2946
    return (schema_tables_add(thd, table_names,
 
2947
                              lookup_field_vals->table_value.str));
 
2948
 
 
2949
  find_files_result res= find_files(thd, table_names, db_name->str, path,
 
2950
                                    lookup_field_vals->table_value.str, 0);
 
2951
  if (res != FIND_FILES_OK)
 
2952
  {
 
2953
    /*
 
2954
      Downgrade errors about problems with database directory to
 
2955
      warnings if this is not a 'SHOW' command.  Another thread
 
2956
      may have dropped database, and we may still have a name
 
2957
      for that directory.
 
2958
    */
 
2959
    if (res == FIND_FILES_DIR)
 
2960
    {
 
2961
      if (lex->sql_command != SQLCOM_SELECT)
 
2962
        return 1;
 
2963
      thd->clear_error();
 
2964
      return 2;
 
2965
    }
 
2966
    return 1;
 
2967
  }
 
2968
  return 0;
 
2969
}
 
2970
 
 
2971
 
 
2972
/**
 
2973
  @brief          Fill I_S table for SHOW COLUMNS|INDEX commands
 
2974
 
 
2975
  @param[in]      thd                      thread handler
 
2976
  @param[in]      tables                   TABLE_LIST for I_S table
 
2977
  @param[in]      schema_table             pointer to I_S structure
 
2978
  @param[in]      open_tables_state_backup pointer to Open_tables_state object
 
2979
                                           which is used to save|restore original
 
2980
                                           status of variables related to
 
2981
                                           open tables state
 
2982
 
 
2983
  @return         Operation status
 
2984
    @retval       0           success
 
2985
    @retval       1           error
 
2986
*/
 
2987
 
 
2988
static int 
 
2989
fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables,
 
2990
                              ST_SCHEMA_TABLE *schema_table,
 
2991
                              Open_tables_state *open_tables_state_backup)
 
2992
{
 
2993
  LEX *lex= thd->lex;
 
2994
  bool res;
 
2995
  LEX_STRING tmp_lex_string, tmp_lex_string1, *db_name, *table_name;
 
2996
  enum_sql_command save_sql_command= lex->sql_command;
 
2997
  TABLE_LIST *show_table_list= (TABLE_LIST*) tables->schema_select_lex->
 
2998
    table_list.first;
 
2999
  TABLE *table= tables->table;
 
3000
  int error= 1;
 
3001
  DBUG_ENTER("fill_schema_show");
 
3002
 
 
3003
  lex->all_selects_list= tables->schema_select_lex;
 
3004
  /*
 
3005
    Restore thd->temporary_tables to be able to process
 
3006
    temporary tables(only for 'show index' & 'show columns').
 
3007
    This should be changed when processing of temporary tables for
 
3008
    I_S tables will be done.
 
3009
  */
 
3010
  thd->temporary_tables= open_tables_state_backup->temporary_tables;
 
3011
  /*
 
3012
    Let us set fake sql_command so views won't try to merge
 
3013
    themselves into main statement. If we don't do this,
 
3014
    SELECT * from information_schema.xxxx will cause problems.
 
3015
    SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()' 
 
3016
  */
 
3017
  lex->sql_command= SQLCOM_SHOW_FIELDS;
 
3018
  res= open_normal_and_derived_tables(thd, show_table_list,
 
3019
                                      MYSQL_LOCK_IGNORE_FLUSH);
 
3020
  lex->sql_command= save_sql_command;
 
3021
  /*
 
3022
    get_all_tables() returns 1 on failure and 0 on success thus
 
3023
    return only these and not the result code of ::process_table()
 
3024
 
 
3025
    We should use show_table_list->alias instead of 
 
3026
    show_table_list->table_name because table_name
 
3027
    could be changed during opening of I_S tables. It's safe
 
3028
    to use alias because alias contains original table name 
 
3029
    in this case(this part of code is used only for 
 
3030
    'show columns' & 'show statistics' commands).
 
3031
  */
 
3032
   table_name= thd->make_lex_string(&tmp_lex_string1, show_table_list->alias,
 
3033
                                    strlen(show_table_list->alias), FALSE);
 
3034
   if (!show_table_list->view)
 
3035
     db_name= thd->make_lex_string(&tmp_lex_string, show_table_list->db,
 
3036
                                   show_table_list->db_length, FALSE);
 
3037
   else
 
3038
     db_name= &show_table_list->view_db;
 
3039
      
 
3040
 
 
3041
   error= test(schema_table->process_table(thd, show_table_list,
 
3042
                                           table, res, db_name,
 
3043
                                           table_name));
 
3044
   thd->temporary_tables= 0;
 
3045
   close_tables_for_reopen(thd, &show_table_list);
 
3046
   DBUG_RETURN(error);
 
3047
}
 
3048
 
 
3049
 
 
3050
/**
 
3051
  @brief          Fill I_S table for SHOW TABLE NAMES commands
 
3052
 
 
3053
  @param[in]      thd                      thread handler
 
3054
  @param[in]      table                    TABLE struct for I_S table
 
3055
  @param[in]      db_name                  database name
 
3056
  @param[in]      table_name               table name
 
3057
  @param[in]      with_i_schema            I_S table if TRUE
 
3058
 
 
3059
  @return         Operation status
 
3060
    @retval       0           success
 
3061
    @retval       1           error
 
3062
*/
 
3063
 
 
3064
static int fill_schema_table_names(THD *thd, TABLE *table,
 
3065
                                   LEX_STRING *db_name, LEX_STRING *table_name,
 
3066
                                   bool with_i_schema)
 
3067
{
 
3068
  if (with_i_schema)
 
3069
  {
 
3070
    table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
 
3071
                           system_charset_info);
 
3072
  }
 
3073
  else
 
3074
  {
 
3075
    enum legacy_db_type not_used;
 
3076
    char path[FN_REFLEN + 1];
 
3077
    (void) build_table_filename(path, sizeof(path) - 1, db_name->str, 
 
3078
                                table_name->str, reg_ext, 0);
 
3079
    switch (mysql_frm_type(thd, path, &not_used)) {
 
3080
    case FRMTYPE_ERROR:
 
3081
      table->field[3]->store(STRING_WITH_LEN("ERROR"),
 
3082
                             system_charset_info);
 
3083
      break;
 
3084
    case FRMTYPE_TABLE:
 
3085
      table->field[3]->store(STRING_WITH_LEN("BASE TABLE"),
 
3086
                             system_charset_info);
 
3087
      break;
 
3088
    case FRMTYPE_VIEW:
 
3089
      table->field[3]->store(STRING_WITH_LEN("VIEW"),
 
3090
                             system_charset_info);
 
3091
      break;
 
3092
    default:
 
3093
      DBUG_ASSERT(0);
 
3094
    }
 
3095
    if (thd->is_error() && thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
 
3096
    {
 
3097
      thd->clear_error();
 
3098
      return 0;
 
3099
    }
 
3100
  }
 
3101
  if (schema_table_store_record(thd, table))
 
3102
    return 1;
 
3103
  return 0;
 
3104
}
 
3105
 
 
3106
 
 
3107
/**
 
3108
  @brief          Get open table method
 
3109
 
 
3110
  @details        The function calculates the method which will be used
 
3111
                  for table opening:
 
3112
                  SKIP_OPEN_TABLE - do not open table
 
3113
                  OPEN_FRM_ONLY   - open FRM file only
 
3114
                  OPEN_FULL_TABLE - open FRM, data, index files
 
3115
  @param[in]      tables               I_S table table_list
 
3116
  @param[in]      schema_table         I_S table struct
 
3117
  @param[in]      schema_table_idx     I_S table index
 
3118
 
 
3119
  @return         return a set of flags
 
3120
    @retval       SKIP_OPEN_TABLE | OPEN_FRM_ONLY | OPEN_FULL_TABLE
 
3121
*/
 
3122
 
 
3123
uint get_table_open_method(TABLE_LIST *tables,
 
3124
                                  ST_SCHEMA_TABLE *schema_table,
 
3125
                                  enum enum_schema_tables schema_table_idx)
 
3126
{
 
3127
  /*
 
3128
    determine which method will be used for table opening
 
3129
  */
 
3130
  if (schema_table->i_s_requested_object & OPTIMIZE_I_S_TABLE)
 
3131
  {
 
3132
    Field **ptr, *field;
 
3133
    int table_open_method= 0, field_indx= 0;
 
3134
    uint star_table_open_method= OPEN_FULL_TABLE;
 
3135
    bool used_star= true;                  // true if '*' is used in select
 
3136
    for (ptr=tables->table->field; (field= *ptr) ; ptr++)
 
3137
    {
 
3138
      star_table_open_method=
 
3139
        min(star_table_open_method,
 
3140
            schema_table->fields_info[field_indx].open_method);
 
3141
      if (bitmap_is_set(tables->table->read_set, field->field_index))
 
3142
      {
 
3143
        used_star= false;
 
3144
        table_open_method|= schema_table->fields_info[field_indx].open_method;
 
3145
      }
 
3146
      field_indx++;
 
3147
    }
 
3148
    if (used_star)
 
3149
      return star_table_open_method;
 
3150
    return table_open_method;
 
3151
  }
 
3152
  /* I_S tables which use get_all_tables but can not be optimized */
 
3153
  return (uint) OPEN_FULL_TABLE;
 
3154
}
 
3155
 
 
3156
 
 
3157
/**
 
3158
  @brief          Fill I_S table with data from FRM file only
 
3159
 
 
3160
  @param[in]      thd                      thread handler
 
3161
  @param[in]      table                    TABLE struct for I_S table
 
3162
  @param[in]      schema_table             I_S table struct
 
3163
  @param[in]      db_name                  database name
 
3164
  @param[in]      table_name               table name
 
3165
  @param[in]      schema_table_idx         I_S table index
 
3166
 
 
3167
  @return         Operation status
 
3168
    @retval       0           Table is processed and we can continue
 
3169
                              with new table
 
3170
    @retval       1           It's view and we have to use
 
3171
                              open_tables function for this table
 
3172
*/
 
3173
 
 
3174
static int fill_schema_table_from_frm(THD *thd,TABLE *table,
 
3175
                                      ST_SCHEMA_TABLE *schema_table, 
 
3176
                                      LEX_STRING *db_name,
 
3177
                                      LEX_STRING *table_name,
 
3178
                                      enum enum_schema_tables schema_table_idx)
 
3179
{
 
3180
  TABLE_SHARE *share;
 
3181
  TABLE tbl;
 
3182
  TABLE_LIST table_list;
 
3183
  uint res= 0;
 
3184
  int error;
 
3185
  char key[MAX_DBKEY_LENGTH];
 
3186
  uint key_length;
 
3187
 
 
3188
  bzero((char*) &table_list, sizeof(TABLE_LIST));
 
3189
  bzero((char*) &tbl, sizeof(TABLE));
 
3190
 
 
3191
  table_list.table_name= table_name->str;
 
3192
  table_list.db= db_name->str;
 
3193
  key_length= create_table_def_key(thd, key, &table_list, 0);
 
3194
  pthread_mutex_lock(&LOCK_open);
 
3195
  share= get_table_share(thd, &table_list, key,
 
3196
                         key_length, OPEN_VIEW, &error);
 
3197
  if (!share)
 
3198
  {
 
3199
    res= 0;
 
3200
    goto err;
 
3201
  }
 
3202
 
 
3203
  if (share->is_view)
 
3204
  {
 
3205
    if (schema_table->i_s_requested_object & OPEN_TABLE_ONLY)
 
3206
    {
 
3207
      /* skip view processing */
 
3208
      res= 0;
 
3209
      goto err1;
 
3210
    }
 
3211
    else if (schema_table->i_s_requested_object & OPEN_VIEW_FULL)
 
3212
    {
 
3213
      /*
 
3214
        tell get_all_tables() to fall back to 
 
3215
        open_normal_and_derived_tables()
 
3216
      */
 
3217
      res= 1;
 
3218
      goto err1;
 
3219
    }
 
3220
  }
 
3221
 
 
3222
  if (share->is_view ||
 
3223
      !open_table_from_share(thd, share, table_name->str, 0,
 
3224
                             (READ_KEYINFO | COMPUTE_TYPES |
 
3225
                              EXTRA_RECORD | OPEN_FRM_FILE_ONLY),
 
3226
                             thd->open_options, &tbl, FALSE))
 
3227
  {
 
3228
    tbl.s= share;
 
3229
    table_list.table= &tbl;
 
3230
    table_list.view= (st_lex*) share->is_view;
 
3231
    res= schema_table->process_table(thd, &table_list, table,
 
3232
                                     res, db_name, table_name);
 
3233
    closefrm(&tbl, true);
 
3234
    goto err;
 
3235
  }
 
3236
 
 
3237
err1:
 
3238
  release_table_share(share, RELEASE_NORMAL);
 
3239
 
 
3240
err:
 
3241
  pthread_mutex_unlock(&LOCK_open);
 
3242
  thd->clear_error();
 
3243
  return res;
 
3244
}
 
3245
 
 
3246
 
 
3247
 
 
3248
/**
 
3249
  @brief          Fill I_S tables whose data are retrieved
 
3250
                  from frm files and storage engine
 
3251
 
 
3252
  @details        The information schema tables are internally represented as
 
3253
                  temporary tables that are filled at query execution time.
 
3254
                  Those I_S tables whose data are retrieved
 
3255
                  from frm files and storage engine are filled by the function
 
3256
                  get_all_tables().
 
3257
 
 
3258
  @param[in]      thd                      thread handler
 
3259
  @param[in]      tables                   I_S table
 
3260
  @param[in]      cond                     'WHERE' condition
 
3261
 
 
3262
  @return         Operation status
 
3263
    @retval       0                        success
 
3264
    @retval       1                        error
 
3265
*/
 
3266
 
 
3267
int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
 
3268
{
 
3269
  LEX *lex= thd->lex;
 
3270
  TABLE *table= tables->table;
 
3271
  SELECT_LEX *old_all_select_lex= lex->all_selects_list;
 
3272
  enum_sql_command save_sql_command= lex->sql_command;
 
3273
  SELECT_LEX *lsel= tables->schema_select_lex;
 
3274
  ST_SCHEMA_TABLE *schema_table= tables->schema_table;
 
3275
  SELECT_LEX sel;
 
3276
  LOOKUP_FIELD_VALUES lookup_field_vals;
 
3277
  LEX_STRING *db_name, *table_name;
 
3278
  bool with_i_schema;
 
3279
  enum enum_schema_tables schema_table_idx;
 
3280
  List<LEX_STRING> db_names;
 
3281
  List_iterator_fast<LEX_STRING> it(db_names);
 
3282
  COND *partial_cond= 0;
 
3283
  uint derived_tables= lex->derived_tables; 
 
3284
  int error= 1;
 
3285
  Open_tables_state open_tables_state_backup;
 
3286
  bool save_view_prepare_mode= lex->view_prepare_mode;
 
3287
  Query_tables_list query_tables_list_backup;
 
3288
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
3289
  Security_context *sctx= thd->security_ctx;
 
3290
#endif
 
3291
  uint table_open_method;
 
3292
  DBUG_ENTER("get_all_tables");
 
3293
 
 
3294
  lex->view_prepare_mode= TRUE;
 
3295
  lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
 
3296
 
 
3297
  /*
 
3298
    We should not introduce deadlocks even if we already have some
 
3299
    tables open and locked, since we won't lock tables which we will
 
3300
    open and will ignore possible name-locks for these tables.
 
3301
  */
 
3302
  thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
 
3303
 
 
3304
  /* 
 
3305
    this branch processes SHOW FIELDS, SHOW INDEXES commands.
 
3306
    see sql_parse.cc, prepare_schema_table() function where
 
3307
    this values are initialized
 
3308
  */
 
3309
  if (lsel && lsel->table_list.first)
 
3310
  {
 
3311
    error= fill_schema_show_cols_or_idxs(thd, tables, schema_table,
 
3312
                                         &open_tables_state_backup);
 
3313
    goto err;
 
3314
  }
 
3315
 
 
3316
  schema_table_idx= get_schema_table_idx(schema_table);
 
3317
  if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals))
 
3318
  {
 
3319
    error= 0;
 
3320
    goto err;
 
3321
  }
 
3322
  DBUG_PRINT("INDEX VALUES",("db_name='%s', table_name='%s'",
 
3323
                             STR_OR_NIL(lookup_field_vals.db_value.str),
 
3324
                             STR_OR_NIL(lookup_field_vals.table_value.str)));
 
3325
 
 
3326
  if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value)
 
3327
  {
 
3328
    /* 
 
3329
      if lookup value is empty string then
 
3330
      it's impossible table name or db name
 
3331
    */
 
3332
    if ((lookup_field_vals.db_value.str &&
 
3333
         !lookup_field_vals.db_value.str[0]) ||
 
3334
        (lookup_field_vals.table_value.str &&
 
3335
         !lookup_field_vals.table_value.str[0]))
 
3336
    {
 
3337
      error= 0;
 
3338
      goto err;
 
3339
    }
 
3340
  }
 
3341
 
 
3342
  if (lookup_field_vals.db_value.length &&
 
3343
      !lookup_field_vals.wild_db_value)
 
3344
    tables->has_db_lookup_value= TRUE;
 
3345
  if (lookup_field_vals.table_value.length &&
 
3346
      !lookup_field_vals.wild_table_value) 
 
3347
    tables->has_table_lookup_value= TRUE;
 
3348
 
 
3349
  if (tables->has_db_lookup_value && tables->has_table_lookup_value)
 
3350
    partial_cond= 0;
 
3351
  else
 
3352
    partial_cond= make_cond_for_info_schema(cond, tables);
 
3353
 
 
3354
  tables->table_open_method= table_open_method=
 
3355
    get_table_open_method(tables, schema_table, schema_table_idx);
 
3356
 
 
3357
  if (lex->describe)
 
3358
  {
 
3359
    /* EXPLAIN SELECT */
 
3360
    error= 0;
 
3361
    goto err;
 
3362
  }
 
3363
 
 
3364
  if (make_db_list(thd, &db_names, &lookup_field_vals, &with_i_schema))
 
3365
    goto err;
 
3366
  it.rewind(); /* To get access to new elements in basis list */
 
3367
  while ((db_name= it++))
 
3368
  {
 
3369
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
3370
    if (!(check_access(thd,SELECT_ACL, db_name->str, 
 
3371
                       &thd->col_access, 0, 1, with_i_schema) ||
 
3372
          (!thd->col_access && check_grant_db(thd, db_name->str))) ||
 
3373
        sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
 
3374
        acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0))
 
3375
#endif
 
3376
    {
 
3377
      thd->no_warnings_for_error= 1;
 
3378
      List<LEX_STRING> table_names;
 
3379
      int res= make_table_name_list(thd, &table_names, lex,
 
3380
                                    &lookup_field_vals,
 
3381
                                    with_i_schema, db_name);
 
3382
      if (res == 2)   /* Not fatal error, continue */
 
3383
        continue;
 
3384
      if (res)
 
3385
        goto err;
 
3386
 
 
3387
      List_iterator_fast<LEX_STRING> it_files(table_names);
 
3388
      while ((table_name= it_files++))
 
3389
      {
 
3390
        restore_record(table, s->default_values);
 
3391
        table->field[schema_table->idx_field1]->
 
3392
          store(db_name->str, db_name->length, system_charset_info);
 
3393
        table->field[schema_table->idx_field2]->
 
3394
          store(table_name->str, table_name->length, system_charset_info);
 
3395
 
 
3396
        if (!partial_cond || partial_cond->val_int())
 
3397
        {
 
3398
          /*
 
3399
            If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN)
 
3400
            we can skip table opening and we don't have lookup value for 
 
3401
            table name or lookup value is wild string(table name list is
 
3402
            already created by make_table_name_list() function).
 
3403
          */
 
3404
          if (!table_open_method && schema_table_idx == SCH_TABLES &&
 
3405
              (!lookup_field_vals.table_value.length ||
 
3406
               lookup_field_vals.wild_table_value))
 
3407
          {
 
3408
            if (schema_table_store_record(thd, table))
 
3409
              goto err;      /* Out of space in temporary table */
 
3410
            continue;
 
3411
          }
 
3412
 
 
3413
          /* SHOW TABLE NAMES command */
 
3414
          if (schema_table_idx == SCH_TABLE_NAMES)
 
3415
          {
 
3416
            if (fill_schema_table_names(thd, tables->table, db_name,
 
3417
                                        table_name, with_i_schema))
 
3418
              continue;
 
3419
          }
 
3420
          else
 
3421
          {
 
3422
            if (!(table_open_method & ~OPEN_FRM_ONLY) && 
 
3423
                !with_i_schema)
 
3424
            {
 
3425
              if (!fill_schema_table_from_frm(thd, table, schema_table, db_name,
 
3426
                                              table_name, schema_table_idx))
 
3427
                continue;
 
3428
            }
 
3429
 
 
3430
            int res;
 
3431
            LEX_STRING tmp_lex_string, orig_db_name;
 
3432
            /*
 
3433
              Set the parent lex of 'sel' because it is needed by
 
3434
              sel.init_query() which is called inside make_table_list.
 
3435
            */
 
3436
            thd->no_warnings_for_error= 1;
 
3437
            sel.parent_lex= lex;
 
3438
            /* db_name can be changed in make_table_list() func */
 
3439
            if (!thd->make_lex_string(&orig_db_name, db_name->str,
 
3440
                                      db_name->length, FALSE))
 
3441
              goto err;
 
3442
            if (make_table_list(thd, &sel, db_name, table_name))
 
3443
              goto err;
 
3444
            TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first;
 
3445
            lex->all_selects_list= &sel;
 
3446
            lex->derived_tables= 0;
 
3447
            lex->sql_command= SQLCOM_SHOW_FIELDS;
 
3448
            show_table_list->i_s_requested_object=
 
3449
              schema_table->i_s_requested_object;
 
3450
            res= open_normal_and_derived_tables(thd, show_table_list,
 
3451
                                                MYSQL_LOCK_IGNORE_FLUSH);
 
3452
            lex->sql_command= save_sql_command;
 
3453
            /*
 
3454
              XXX:  show_table_list has a flag i_is_requested,
 
3455
              and when it's set, open_normal_and_derived_tables()
 
3456
              can return an error without setting an error message
 
3457
              in THD, which is a hack. This is why we have to
 
3458
              check for res, then for thd->is_error() only then
 
3459
              for thd->main_da.sql_errno().
 
3460
            */
 
3461
            if (res && thd->is_error() &&
 
3462
                thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
 
3463
            {
 
3464
              /*
 
3465
                Hide error for not existing table.
 
3466
                This error can occur for example when we use
 
3467
                where condition with db name and table name and this
 
3468
                table does not exist.
 
3469
              */
 
3470
              res= 0;
 
3471
              thd->clear_error();
 
3472
            }
 
3473
            else
 
3474
            {
 
3475
              /*
 
3476
                We should use show_table_list->alias instead of 
 
3477
                show_table_list->table_name because table_name
 
3478
                could be changed during opening of I_S tables. It's safe
 
3479
                to use alias because alias contains original table name 
 
3480
                in this case.
 
3481
              */
 
3482
              thd->make_lex_string(&tmp_lex_string, show_table_list->alias,
 
3483
                                   strlen(show_table_list->alias), FALSE);
 
3484
              res= schema_table->process_table(thd, show_table_list, table,
 
3485
                                               res, &orig_db_name,
 
3486
                                               &tmp_lex_string);
 
3487
              close_tables_for_reopen(thd, &show_table_list);
 
3488
            }
 
3489
            DBUG_ASSERT(!lex->query_tables_own_last);
 
3490
            if (res)
 
3491
              goto err;
 
3492
          }
 
3493
        }
 
3494
      }
 
3495
      /*
 
3496
        If we have information schema its always the first table and only
 
3497
        the first table. Reset for other tables.
 
3498
      */
 
3499
      with_i_schema= 0;
 
3500
    }
 
3501
  }
 
3502
 
 
3503
  error= 0;
 
3504
err:
 
3505
  thd->restore_backup_open_tables_state(&open_tables_state_backup);
 
3506
  lex->restore_backup_query_tables_list(&query_tables_list_backup);
 
3507
  lex->derived_tables= derived_tables;
 
3508
  lex->all_selects_list= old_all_select_lex;
 
3509
  lex->view_prepare_mode= save_view_prepare_mode;
 
3510
  lex->sql_command= save_sql_command;
 
3511
  DBUG_RETURN(error);
 
3512
}
 
3513
 
 
3514
 
 
3515
bool store_schema_shemata(THD* thd, TABLE *table, LEX_STRING *db_name,
 
3516
                          CHARSET_INFO *cs)
 
3517
{
 
3518
  restore_record(table, s->default_values);
 
3519
  table->field[1]->store(db_name->str, db_name->length, system_charset_info);
 
3520
  table->field[2]->store(cs->csname, strlen(cs->csname), system_charset_info);
 
3521
  table->field[3]->store(cs->name, strlen(cs->name), system_charset_info);
 
3522
  return schema_table_store_record(thd, table);
 
3523
}
 
3524
 
 
3525
 
 
3526
int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond)
 
3527
{
 
3528
  /*
 
3529
    TODO: fill_schema_shemata() is called when new client is connected.
 
3530
    Returning error status in this case leads to client hangup.
 
3531
  */
 
3532
 
 
3533
  LOOKUP_FIELD_VALUES lookup_field_vals;
 
3534
  List<LEX_STRING> db_names;
 
3535
  LEX_STRING *db_name;
 
3536
  bool with_i_schema;
 
3537
  HA_CREATE_INFO create;
 
3538
  TABLE *table= tables->table;
 
3539
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
3540
  Security_context *sctx= thd->security_ctx;
 
3541
#endif
 
3542
  DBUG_ENTER("fill_schema_shemata");
 
3543
 
 
3544
  if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals))
 
3545
    DBUG_RETURN(0);
 
3546
  DBUG_PRINT("INDEX VALUES",("db_name='%s', table_name='%s'",
 
3547
                             lookup_field_vals.db_value.str,
 
3548
                             lookup_field_vals.table_value.str));
 
3549
  if (make_db_list(thd, &db_names, &lookup_field_vals,
 
3550
                   &with_i_schema))
 
3551
    DBUG_RETURN(1);
 
3552
 
 
3553
  /*
 
3554
    If we have lookup db value we should check that the database exists
 
3555
  */
 
3556
  if(lookup_field_vals.db_value.str && !lookup_field_vals.wild_db_value &&
 
3557
     !with_i_schema)
 
3558
  {
 
3559
    char path[FN_REFLEN+16];
 
3560
    uint path_len;
 
3561
    MY_STAT stat_info;
 
3562
    if (!lookup_field_vals.db_value.str[0])
 
3563
      DBUG_RETURN(0);
 
3564
    path_len= build_table_filename(path, sizeof(path) - 1,
 
3565
                                   lookup_field_vals.db_value.str, "", "", 0);
 
3566
    path[path_len-1]= 0;
 
3567
    if (!my_stat(path,&stat_info,MYF(0)))
 
3568
      DBUG_RETURN(0);
 
3569
  }
 
3570
 
 
3571
  List_iterator_fast<LEX_STRING> it(db_names);
 
3572
  while ((db_name=it++))
 
3573
  {
 
3574
    if (with_i_schema)       // information schema name is always first in list
 
3575
    {
 
3576
      if (store_schema_shemata(thd, table, db_name,
 
3577
                               system_charset_info))
 
3578
        DBUG_RETURN(1);
 
3579
      with_i_schema= 0;
 
3580
      continue;
 
3581
    }
 
3582
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
3583
    if (sctx->master_access & (DB_ACLS | SHOW_DB_ACL) ||
 
3584
        acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0) ||
 
3585
        !check_grant_db(thd, db_name->str))
 
3586
#endif
 
3587
    {
 
3588
      load_db_opt_by_name(thd, db_name->str, &create);
 
3589
      if (store_schema_shemata(thd, table, db_name,
 
3590
                               create.default_table_charset))
 
3591
        DBUG_RETURN(1);
 
3592
    }
 
3593
  }
 
3594
  DBUG_RETURN(0);
 
3595
}
 
3596
 
 
3597
 
 
3598
static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
 
3599
                                    TABLE *table, bool res,
 
3600
                                    LEX_STRING *db_name,
 
3601
                                    LEX_STRING *table_name)
 
3602
{
 
3603
  const char *tmp_buff;
 
3604
  MYSQL_TIME time;
 
3605
  CHARSET_INFO *cs= system_charset_info;
 
3606
  DBUG_ENTER("get_schema_tables_record");
 
3607
 
 
3608
  restore_record(table, s->default_values);
 
3609
  table->field[1]->store(db_name->str, db_name->length, cs);
 
3610
  table->field[2]->store(table_name->str, table_name->length, cs);
 
3611
  if (res)
 
3612
  {
 
3613
    /*
 
3614
      there was errors during opening tables
 
3615
    */
 
3616
    const char *error= thd->is_error() ? thd->main_da.message() : "";
 
3617
    if (tables->view)
 
3618
      table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
 
3619
    else if (tables->schema_table)
 
3620
      table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
 
3621
    else
 
3622
      table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
 
3623
    table->field[20]->store(error, strlen(error), cs);
 
3624
    thd->clear_error();
 
3625
  }
 
3626
  else if (tables->view)
 
3627
  {
 
3628
    table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
 
3629
    table->field[20]->store(STRING_WITH_LEN("VIEW"), cs);
 
3630
  }
 
3631
  else
 
3632
  {
 
3633
    char option_buff[350],*ptr;
 
3634
    TABLE *show_table= tables->table;
 
3635
    TABLE_SHARE *share= show_table->s;
 
3636
    handler *file= show_table->file;
 
3637
    handlerton *tmp_db_type= share->db_type();
 
3638
#ifdef WITH_PARTITION_STORAGE_ENGINE
 
3639
    bool is_partitioned= FALSE;
 
3640
#endif
 
3641
    if (share->tmp_table == SYSTEM_TMP_TABLE)
 
3642
      table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs);
 
3643
    else if (share->tmp_table)
 
3644
      table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs);
 
3645
    else
 
3646
      table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs);
 
3647
 
 
3648
    for (int i= 4; i < 20; i++)
 
3649
    {
 
3650
      if (i == 7 || (i > 12 && i < 17) || i == 18)
 
3651
        continue;
 
3652
      table->field[i]->set_notnull();
 
3653
    }
 
3654
#ifdef WITH_PARTITION_STORAGE_ENGINE
 
3655
    if (share->db_type() == partition_hton &&
 
3656
        share->partition_info_len)
 
3657
    {
 
3658
      tmp_db_type= share->default_part_db_type;
 
3659
      is_partitioned= TRUE;
 
3660
    }
 
3661
#endif
 
3662
    tmp_buff= (char *) ha_resolve_storage_engine_name(tmp_db_type);
 
3663
    table->field[4]->store(tmp_buff, strlen(tmp_buff), cs);
 
3664
    table->field[5]->store((longlong) share->frm_version, TRUE);
 
3665
 
 
3666
    ptr=option_buff;
 
3667
    if (share->min_rows)
 
3668
    {
 
3669
      ptr=strmov(ptr," min_rows=");
 
3670
      ptr=longlong10_to_str(share->min_rows,ptr,10);
 
3671
    }
 
3672
    if (share->max_rows)
 
3673
    {
 
3674
      ptr=strmov(ptr," max_rows=");
 
3675
      ptr=longlong10_to_str(share->max_rows,ptr,10);
 
3676
    }
 
3677
    if (share->avg_row_length)
 
3678
    {
 
3679
      ptr=strmov(ptr," avg_row_length=");
 
3680
      ptr=longlong10_to_str(share->avg_row_length,ptr,10);
 
3681
    }
 
3682
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
 
3683
      ptr=strmov(ptr," pack_keys=1");
 
3684
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
 
3685
      ptr=strmov(ptr," pack_keys=0");
 
3686
    /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */
 
3687
    if (share->db_create_options & HA_OPTION_CHECKSUM)
 
3688
      ptr=strmov(ptr," checksum=1");
 
3689
    if (share->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
 
3690
      ptr=strmov(ptr," delay_key_write=1");
 
3691
    if (share->row_type != ROW_TYPE_DEFAULT)
 
3692
      ptr=strxmov(ptr, " row_format=", 
 
3693
                  ha_row_type[(uint) share->row_type],
 
3694
                  NullS);
 
3695
    if (share->key_block_size)
 
3696
    {
 
3697
      ptr= strmov(ptr, " KEY_BLOCK_SIZE=");
 
3698
      ptr= longlong10_to_str(share->key_block_size, ptr, 10);
 
3699
    }
 
3700
#ifdef WITH_PARTITION_STORAGE_ENGINE
 
3701
    if (is_partitioned)
 
3702
      ptr= strmov(ptr, " partitioned");
 
3703
#endif
 
3704
    table->field[19]->store(option_buff+1,
 
3705
                            (ptr == option_buff ? 0 : 
 
3706
                             (uint) (ptr-option_buff)-1), cs);
 
3707
 
 
3708
    tmp_buff= (share->table_charset ?
 
3709
               share->table_charset->name : "default");
 
3710
    table->field[17]->store(tmp_buff, strlen(tmp_buff), cs);
 
3711
 
 
3712
    if (share->comment.str)
 
3713
      table->field[20]->store(share->comment.str, share->comment.length, cs);
 
3714
 
 
3715
    if(file)
 
3716
    {
 
3717
      file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_AUTO);
 
3718
      enum row_type row_type = file->get_row_type();
 
3719
      switch (row_type) {
 
3720
      case ROW_TYPE_NOT_USED:
 
3721
      case ROW_TYPE_DEFAULT:
 
3722
        tmp_buff= ((share->db_options_in_use &
 
3723
                    HA_OPTION_COMPRESS_RECORD) ? "Compressed" :
 
3724
                   (share->db_options_in_use & HA_OPTION_PACK_RECORD) ?
 
3725
                   "Dynamic" : "Fixed");
 
3726
        break;
 
3727
      case ROW_TYPE_FIXED:
 
3728
        tmp_buff= "Fixed";
 
3729
        break;
 
3730
      case ROW_TYPE_DYNAMIC:
 
3731
        tmp_buff= "Dynamic";
 
3732
        break;
 
3733
      case ROW_TYPE_COMPRESSED:
 
3734
        tmp_buff= "Compressed";
 
3735
        break;
 
3736
      case ROW_TYPE_REDUNDANT:
 
3737
        tmp_buff= "Redundant";
 
3738
        break;
 
3739
      case ROW_TYPE_COMPACT:
 
3740
        tmp_buff= "Compact";
 
3741
        break;
 
3742
      case ROW_TYPE_PAGE:
 
3743
        tmp_buff= "Paged";
 
3744
        break;
 
3745
      }
 
3746
      table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
 
3747
      if (!tables->schema_table)
 
3748
      {
 
3749
        table->field[7]->store((longlong) file->stats.records, TRUE);
 
3750
        table->field[7]->set_notnull();
 
3751
      }
 
3752
      table->field[8]->store((longlong) file->stats.mean_rec_length, TRUE);
 
3753
      table->field[9]->store((longlong) file->stats.data_file_length, TRUE);
 
3754
      if (file->stats.max_data_file_length)
 
3755
      {
 
3756
        table->field[10]->store((longlong) file->stats.max_data_file_length,
 
3757
                                TRUE);
 
3758
      }
 
3759
      table->field[11]->store((longlong) file->stats.index_file_length, TRUE);
 
3760
      table->field[12]->store((longlong) file->stats.delete_length, TRUE);
 
3761
      if (show_table->found_next_number_field)
 
3762
      {
 
3763
        table->field[13]->store((longlong) file->stats.auto_increment_value,
 
3764
                                TRUE);
 
3765
        table->field[13]->set_notnull();
 
3766
      }
 
3767
      if (file->stats.create_time)
 
3768
      {
 
3769
        thd->variables.time_zone->gmt_sec_to_TIME(&time,
 
3770
                                                  (my_time_t) file->stats.create_time);
 
3771
        table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
3772
        table->field[14]->set_notnull();
 
3773
      }
 
3774
      if (file->stats.update_time)
 
3775
      {
 
3776
        thd->variables.time_zone->gmt_sec_to_TIME(&time,
 
3777
                                                  (my_time_t) file->stats.update_time);
 
3778
        table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
3779
        table->field[15]->set_notnull();
 
3780
      }
 
3781
      if (file->stats.check_time)
 
3782
      {
 
3783
        thd->variables.time_zone->gmt_sec_to_TIME(&time,
 
3784
                                                  (my_time_t) file->stats.check_time);
 
3785
        table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
3786
        table->field[16]->set_notnull();
 
3787
      }
 
3788
      if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
 
3789
      {
 
3790
        table->field[18]->store((longlong) file->checksum(), TRUE);
 
3791
        table->field[18]->set_notnull();
 
3792
      }
 
3793
    }
 
3794
  }
 
3795
  DBUG_RETURN(schema_table_store_record(thd, table));
 
3796
}
 
3797
 
 
3798
 
 
3799
static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
 
3800
                                    TABLE *table, bool res,
 
3801
                                    LEX_STRING *db_name,
 
3802
                                    LEX_STRING *table_name)
 
3803
{
 
3804
  LEX *lex= thd->lex;
 
3805
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
 
3806
  CHARSET_INFO *cs= system_charset_info;
 
3807
  TABLE *show_table;
 
3808
  Field **ptr,*field;
 
3809
  int count;
 
3810
  DBUG_ENTER("get_schema_column_record");
 
3811
 
 
3812
  if (res)
 
3813
  {
 
3814
    if (lex->sql_command != SQLCOM_SHOW_FIELDS)
 
3815
    {
 
3816
      /*
 
3817
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
 
3818
        rather than in SHOW COLUMNS
 
3819
      */ 
 
3820
      if (thd->is_error())
 
3821
        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
3822
                     thd->main_da.sql_errno(), thd->main_da.message());
 
3823
      thd->clear_error();
 
3824
      res= 0;
 
3825
    }
 
3826
    DBUG_RETURN(res);
 
3827
  }
 
3828
 
 
3829
  show_table= tables->table;
 
3830
  count= 0;
 
3831
  restore_record(show_table, s->default_values);
 
3832
  show_table->use_all_columns();               // Required for default
 
3833
 
 
3834
  for (ptr= show_table->field; (field= *ptr) ; ptr++)
 
3835
  {
 
3836
    const char *tmp_buff;
 
3837
    uchar *pos;
 
3838
    bool is_blob;
 
3839
    uint flags=field->flags;
 
3840
    char tmp[MAX_FIELD_WIDTH];
 
3841
    String type(tmp,sizeof(tmp), system_charset_info);
 
3842
    char *end;
 
3843
    int decimals, field_length;
 
3844
 
 
3845
    if (wild && wild[0] &&
 
3846
        wild_case_compare(system_charset_info, field->field_name,wild))
 
3847
      continue;
 
3848
 
 
3849
    flags= field->flags;
 
3850
    count++;
 
3851
    /* Get default row, with all NULL fields set to NULL */
 
3852
    restore_record(table, s->default_values);
 
3853
 
 
3854
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
3855
    uint col_access;
 
3856
    check_access(thd,SELECT_ACL | EXTRA_ACL, db_name->str,
 
3857
                 &tables->grant.privilege, 0, 0, test(tables->schema_table));
 
3858
    col_access= get_column_grant(thd, &tables->grant, 
 
3859
                                 db_name->str, table_name->str,
 
3860
                                 field->field_name) & COL_ACLS;
 
3861
    if (!tables->schema_table && !col_access)
 
3862
      continue;
 
3863
    end= tmp;
 
3864
    for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
 
3865
    {
 
3866
      if (col_access & 1)
 
3867
      {
 
3868
        *end++=',';
 
3869
        end=strmov(end,grant_types.type_names[bitnr]);
 
3870
      }
 
3871
    }
 
3872
    table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
 
3873
 
 
3874
#endif
 
3875
    table->field[1]->store(db_name->str, db_name->length, cs);
 
3876
    table->field[2]->store(table_name->str, table_name->length, cs);
 
3877
    table->field[3]->store(field->field_name, strlen(field->field_name),
 
3878
                           cs);
 
3879
    table->field[4]->store((longlong) count, TRUE);
 
3880
    field->sql_type(type);
 
3881
    table->field[14]->store(type.ptr(), type.length(), cs);
 
3882
    /*
 
3883
      MySQL column type has the following format:
 
3884
      base_type [(dimension)] [unsigned] [zerofill].
 
3885
      For DATA_TYPE column we extract only base type.
 
3886
    */
 
3887
    tmp_buff= strchr(type.ptr(), '(');
 
3888
    if (!tmp_buff)
 
3889
      /*
 
3890
        if there is no dimention part then check the presence of
 
3891
        [unsigned] [zerofill] attributes and cut them of if exist.
 
3892
      */
 
3893
      tmp_buff= strchr(type.ptr(), ' ');
 
3894
    table->field[7]->store(type.ptr(),
 
3895
                           (tmp_buff ? tmp_buff - type.ptr() :
 
3896
                            type.length()), cs);
 
3897
 
 
3898
    if (get_field_default_value(thd, show_table, field, &type, 0))
 
3899
    {
 
3900
      table->field[5]->store(type.ptr(), type.length(), cs);
 
3901
      table->field[5]->set_notnull();
 
3902
    }
 
3903
    pos=(uchar*) ((flags & NOT_NULL_FLAG) ?  "NO" : "YES");
 
3904
    table->field[6]->store((const char*) pos,
 
3905
                           strlen((const char*) pos), cs);
 
3906
    is_blob= (field->type() == MYSQL_TYPE_BLOB);
 
3907
    if (field->has_charset() || is_blob ||
 
3908
        field->real_type() == MYSQL_TYPE_VARCHAR ||  // For varbinary type
 
3909
        field->real_type() == MYSQL_TYPE_STRING)     // For binary type
 
3910
    {
 
3911
      uint32 octet_max_length= field->max_display_length();
 
3912
      if (is_blob && octet_max_length != (uint32) 4294967295U)
 
3913
        octet_max_length /= field->charset()->mbmaxlen;
 
3914
      longlong char_max_len= is_blob ? 
 
3915
        (longlong) octet_max_length / field->charset()->mbminlen :
 
3916
        (longlong) octet_max_length / field->charset()->mbmaxlen;
 
3917
      table->field[8]->store(char_max_len, TRUE);
 
3918
      table->field[8]->set_notnull();
 
3919
      table->field[9]->store((longlong) octet_max_length, TRUE);
 
3920
      table->field[9]->set_notnull();
 
3921
    }
 
3922
 
 
3923
    /*
 
3924
      Calculate field_length and decimals.
 
3925
      They are set to -1 if they should not be set (we should return NULL)
 
3926
    */
 
3927
 
 
3928
    decimals= field->decimals();
 
3929
    switch (field->type()) {
 
3930
    case MYSQL_TYPE_NEWDECIMAL:
 
3931
      field_length= ((Field_new_decimal*) field)->precision;
 
3932
      break;
 
3933
    case MYSQL_TYPE_DECIMAL:
 
3934
      field_length= field->field_length - (decimals  ? 2 : 1);
 
3935
      break;
 
3936
    case MYSQL_TYPE_TINY:
 
3937
    case MYSQL_TYPE_SHORT:
 
3938
    case MYSQL_TYPE_LONG:
 
3939
    case MYSQL_TYPE_LONGLONG:
 
3940
    case MYSQL_TYPE_INT24:
 
3941
      field_length= field->max_display_length() - 1;
 
3942
      break;
 
3943
    case MYSQL_TYPE_BIT:
 
3944
      field_length= field->max_display_length();
 
3945
      decimals= -1;                             // return NULL
 
3946
      break;
 
3947
    case MYSQL_TYPE_FLOAT:  
 
3948
    case MYSQL_TYPE_DOUBLE:
 
3949
      field_length= field->field_length;
 
3950
      if (decimals == NOT_FIXED_DEC)
 
3951
        decimals= -1;                           // return NULL
 
3952
    break;
 
3953
    default:
 
3954
      field_length= decimals= -1;
 
3955
      break;
 
3956
    }
 
3957
 
 
3958
    if (field_length >= 0)
 
3959
    {
 
3960
      table->field[10]->store((longlong) field_length, TRUE);
 
3961
      table->field[10]->set_notnull();
 
3962
    }
 
3963
    if (decimals >= 0)
 
3964
    {
 
3965
      table->field[11]->store((longlong) decimals, TRUE);
 
3966
      table->field[11]->set_notnull();
 
3967
    }
 
3968
 
 
3969
    if (field->has_charset())
 
3970
    {
 
3971
      pos=(uchar*) field->charset()->csname;
 
3972
      table->field[12]->store((const char*) pos,
 
3973
                              strlen((const char*) pos), cs);
 
3974
      table->field[12]->set_notnull();
 
3975
      pos=(uchar*) field->charset()->name;
 
3976
      table->field[13]->store((const char*) pos,
 
3977
                              strlen((const char*) pos), cs);
 
3978
      table->field[13]->set_notnull();
 
3979
    }
 
3980
    pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
 
3981
                 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
 
3982
                 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
 
3983
    table->field[15]->store((const char*) pos,
 
3984
                            strlen((const char*) pos), cs);
 
3985
 
 
3986
    end= tmp;
 
3987
    if (field->unireg_check == Field::NEXT_NUMBER)
 
3988
      table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs);
 
3989
    if (show_table->timestamp_field == field &&
 
3990
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
3991
      table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
 
3992
                              cs);
 
3993
 
 
3994
    table->field[18]->store(field->comment.str, field->comment.length, cs);
 
3995
    if (schema_table_store_record(thd, table))
 
3996
      DBUG_RETURN(1);
 
3997
  }
 
3998
  DBUG_RETURN(0);
 
3999
}
 
4000
 
 
4001
 
 
4002
 
 
4003
int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond)
 
4004
{
 
4005
  CHARSET_INFO **cs;
 
4006
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
 
4007
  TABLE *table= tables->table;
 
4008
  CHARSET_INFO *scs= system_charset_info;
 
4009
 
 
4010
  for (cs= all_charsets ; cs < all_charsets+255 ; cs++)
 
4011
  {
 
4012
    CHARSET_INFO *tmp_cs= cs[0];
 
4013
    if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) && 
 
4014
        (tmp_cs->state & MY_CS_AVAILABLE) &&
 
4015
        !(tmp_cs->state & MY_CS_HIDDEN) &&
 
4016
        !(wild && wild[0] &&
 
4017
          wild_case_compare(scs, tmp_cs->csname,wild)))
 
4018
    {
 
4019
      const char *comment;
 
4020
      restore_record(table, s->default_values);
 
4021
      table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs);
 
4022
      table->field[1]->store(tmp_cs->name, strlen(tmp_cs->name), scs);
 
4023
      comment= tmp_cs->comment ? tmp_cs->comment : "";
 
4024
      table->field[2]->store(comment, strlen(comment), scs);
 
4025
      table->field[3]->store((longlong) tmp_cs->mbmaxlen, TRUE);
 
4026
      if (schema_table_store_record(thd, table))
 
4027
        return 1;
 
4028
    }
 
4029
  }
 
4030
  return 0;
 
4031
}
 
4032
 
 
4033
 
 
4034
static my_bool iter_schema_engines(THD *thd, plugin_ref plugin,
 
4035
                                   void *ptable)
 
4036
{
 
4037
  TABLE *table= (TABLE *) ptable;
 
4038
  handlerton *hton= plugin_data(plugin, handlerton *);
 
4039
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
 
4040
  CHARSET_INFO *scs= system_charset_info;
 
4041
  handlerton *default_type= ha_default_handlerton(thd);
 
4042
  DBUG_ENTER("iter_schema_engines");
 
4043
 
 
4044
 
 
4045
  /* Disabled plugins */
 
4046
  if (plugin_state(plugin) != PLUGIN_IS_READY)
 
4047
  {
 
4048
 
 
4049
    struct st_mysql_plugin *plug= plugin_decl(plugin);
 
4050
    if (!(wild && wild[0] &&
 
4051
          wild_case_compare(scs, plug->name,wild)))
 
4052
    {
 
4053
      restore_record(table, s->default_values);
 
4054
      table->field[0]->store(plug->name, strlen(plug->name), scs);
 
4055
      table->field[1]->store(C_STRING_WITH_LEN("NO"), scs);
 
4056
      table->field[2]->store(plug->descr, strlen(plug->descr), scs);
 
4057
      if (schema_table_store_record(thd, table))
 
4058
        DBUG_RETURN(1);
 
4059
    }
 
4060
    DBUG_RETURN(0);
 
4061
  }
 
4062
 
 
4063
  if (!(hton->flags & HTON_HIDDEN))
 
4064
  {
 
4065
    LEX_STRING *name= plugin_name(plugin);
 
4066
    if (!(wild && wild[0] &&
 
4067
          wild_case_compare(scs, name->str,wild)))
 
4068
    {
 
4069
      LEX_STRING yesno[2]= {{ C_STRING_WITH_LEN("NO") },
 
4070
                            { C_STRING_WITH_LEN("YES") }};
 
4071
      LEX_STRING *tmp;
 
4072
      const char *option_name= show_comp_option_name[(int) hton->state];
 
4073
      restore_record(table, s->default_values);
 
4074
 
 
4075
      table->field[0]->store(name->str, name->length, scs);
 
4076
      if (hton->state == SHOW_OPTION_YES && default_type == hton)
 
4077
        option_name= "DEFAULT";
 
4078
      table->field[1]->store(option_name, strlen(option_name), scs);
 
4079
      table->field[2]->store(plugin_decl(plugin)->descr,
 
4080
                             strlen(plugin_decl(plugin)->descr), scs);
 
4081
      tmp= &yesno[test(hton->commit)];
 
4082
      table->field[3]->store(tmp->str, tmp->length, scs);
 
4083
      table->field[3]->set_notnull();
 
4084
      tmp= &yesno[test(hton->prepare)];
 
4085
      table->field[4]->store(tmp->str, tmp->length, scs);
 
4086
      table->field[4]->set_notnull();
 
4087
      tmp= &yesno[test(hton->savepoint_set)];
 
4088
      table->field[5]->store(tmp->str, tmp->length, scs);
 
4089
      table->field[5]->set_notnull();
 
4090
 
 
4091
      if (schema_table_store_record(thd, table))
 
4092
        DBUG_RETURN(1);
 
4093
    }
 
4094
  }
 
4095
  DBUG_RETURN(0);
 
4096
}
 
4097
 
 
4098
int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
 
4099
{
 
4100
  DBUG_ENTER("fill_schema_engines");
 
4101
  if (plugin_foreach_with_mask(thd, iter_schema_engines,
 
4102
                               MYSQL_STORAGE_ENGINE_PLUGIN,
 
4103
                               ~PLUGIN_IS_FREED, tables->table))
 
4104
    DBUG_RETURN(1);
 
4105
  DBUG_RETURN(0);
 
4106
}
 
4107
 
 
4108
 
 
4109
int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
 
4110
{
 
4111
  CHARSET_INFO **cs;
 
4112
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
 
4113
  TABLE *table= tables->table;
 
4114
  CHARSET_INFO *scs= system_charset_info;
 
4115
  for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
 
4116
  {
 
4117
    CHARSET_INFO **cl;
 
4118
    CHARSET_INFO *tmp_cs= cs[0];
 
4119
    if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
 
4120
         (tmp_cs->state & MY_CS_HIDDEN) ||
 
4121
        !(tmp_cs->state & MY_CS_PRIMARY))
 
4122
      continue;
 
4123
    for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
 
4124
    {
 
4125
      CHARSET_INFO *tmp_cl= cl[0];
 
4126
      if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || 
 
4127
          !my_charset_same(tmp_cs, tmp_cl))
 
4128
        continue;
 
4129
      if (!(wild && wild[0] &&
 
4130
          wild_case_compare(scs, tmp_cl->name,wild)))
 
4131
      {
 
4132
        const char *tmp_buff;
 
4133
        restore_record(table, s->default_values);
 
4134
        table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
 
4135
        table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
 
4136
        table->field[2]->store((longlong) tmp_cl->number, TRUE);
 
4137
        tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : "";
 
4138
        table->field[3]->store(tmp_buff, strlen(tmp_buff), scs);
 
4139
        tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
 
4140
        table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
 
4141
        table->field[5]->store((longlong) tmp_cl->strxfrm_multiply, TRUE);
 
4142
        if (schema_table_store_record(thd, table))
 
4143
          return 1;
 
4144
      }
 
4145
    }
 
4146
  }
 
4147
  return 0;
 
4148
}
 
4149
 
 
4150
 
 
4151
int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond)
 
4152
{
 
4153
  CHARSET_INFO **cs;
 
4154
  TABLE *table= tables->table;
 
4155
  CHARSET_INFO *scs= system_charset_info;
 
4156
  for (cs= all_charsets ; cs < all_charsets+255 ; cs++ )
 
4157
  {
 
4158
    CHARSET_INFO **cl;
 
4159
    CHARSET_INFO *tmp_cs= cs[0];
 
4160
    if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) || 
 
4161
        !(tmp_cs->state & MY_CS_PRIMARY))
 
4162
      continue;
 
4163
    for (cl= all_charsets; cl < all_charsets+255 ;cl ++)
 
4164
    {
 
4165
      CHARSET_INFO *tmp_cl= cl[0];
 
4166
      if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) || 
 
4167
          !my_charset_same(tmp_cs,tmp_cl))
 
4168
        continue;
 
4169
      restore_record(table, s->default_values);
 
4170
      table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
 
4171
      table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
 
4172
      if (schema_table_store_record(thd, table))
 
4173
        return 1;
 
4174
    }
 
4175
  }
 
4176
  return 0;
 
4177
}
 
4178
 
 
4179
 
 
4180
bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table,
 
4181
                       const char *wild, bool full_access, const char *sp_user)
 
4182
{
 
4183
  String tmp_string;
 
4184
  String sp_db, sp_name, definer;
 
4185
  MYSQL_TIME time;
 
4186
  LEX *lex= thd->lex;
 
4187
  CHARSET_INFO *cs= system_charset_info;
 
4188
  get_field(thd->mem_root, proc_table->field[0], &sp_db);
 
4189
  get_field(thd->mem_root, proc_table->field[1], &sp_name);
 
4190
  get_field(thd->mem_root, proc_table->field[11], &definer);
 
4191
  if (!full_access)
 
4192
    full_access= !strcmp(sp_user, definer.ptr());
 
4193
  if (!full_access && check_some_routine_access(thd, sp_db.ptr(),
 
4194
                                                sp_name.ptr(),
 
4195
                                                proc_table->field[2]->
 
4196
                                                val_int() ==
 
4197
                                                TYPE_ENUM_PROCEDURE))
 
4198
    return 0;
 
4199
 
 
4200
  if ((lex->sql_command == SQLCOM_SHOW_STATUS_PROC &&
 
4201
      proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE) ||
 
4202
      (lex->sql_command == SQLCOM_SHOW_STATUS_FUNC &&
 
4203
      proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION) ||
 
4204
      (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0)
 
4205
  {
 
4206
    restore_record(table, s->default_values);
 
4207
    if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0))
 
4208
    {
 
4209
      int enum_idx= (int) proc_table->field[5]->val_int();
 
4210
      table->field[3]->store(sp_name.ptr(), sp_name.length(), cs);
 
4211
      get_field(thd->mem_root, proc_table->field[3], &tmp_string);
 
4212
      table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4213
      table->field[2]->store(sp_db.ptr(), sp_db.length(), cs);
 
4214
      get_field(thd->mem_root, proc_table->field[2], &tmp_string);
 
4215
      table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4216
      if (proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION)
 
4217
      {
 
4218
        get_field(thd->mem_root, proc_table->field[9], &tmp_string);
 
4219
        table->field[5]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4220
        table->field[5]->set_notnull();
 
4221
      }
 
4222
      if (full_access)
 
4223
      {
 
4224
        get_field(thd->mem_root, proc_table->field[19], &tmp_string);
 
4225
        table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4226
        table->field[7]->set_notnull();
 
4227
      }
 
4228
      table->field[6]->store(STRING_WITH_LEN("SQL"), cs);
 
4229
      table->field[10]->store(STRING_WITH_LEN("SQL"), cs);
 
4230
      get_field(thd->mem_root, proc_table->field[6], &tmp_string);
 
4231
      table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4232
      table->field[12]->store(sp_data_access_name[enum_idx].str, 
 
4233
                              sp_data_access_name[enum_idx].length , cs);
 
4234
      get_field(thd->mem_root, proc_table->field[7], &tmp_string);
 
4235
      table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4236
      bzero((char *)&time, sizeof(time));
 
4237
      ((Field_timestamp *) proc_table->field[12])->get_time(&time);
 
4238
      table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
4239
      bzero((char *)&time, sizeof(time));
 
4240
      ((Field_timestamp *) proc_table->field[13])->get_time(&time);
 
4241
      table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
4242
      get_field(thd->mem_root, proc_table->field[14], &tmp_string);
 
4243
      table->field[17]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4244
      get_field(thd->mem_root, proc_table->field[15], &tmp_string);
 
4245
      table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4246
      table->field[19]->store(definer.ptr(), definer.length(), cs);
 
4247
 
 
4248
      get_field(thd->mem_root, proc_table->field[16], &tmp_string);
 
4249
      table->field[20]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4250
 
 
4251
      get_field(thd->mem_root, proc_table->field[17], &tmp_string);
 
4252
      table->field[21]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4253
 
 
4254
      get_field(thd->mem_root, proc_table->field[18], &tmp_string);
 
4255
      table->field[22]->store(tmp_string.ptr(), tmp_string.length(), cs);
 
4256
 
 
4257
      return schema_table_store_record(thd, table);
 
4258
    }
 
4259
  }
 
4260
  return 0;
 
4261
}
 
4262
 
 
4263
 
 
4264
int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
 
4265
{
 
4266
  TABLE *proc_table;
 
4267
  TABLE_LIST proc_tables;
 
4268
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
 
4269
  int res= 0;
 
4270
  TABLE *table= tables->table;
 
4271
  bool full_access;
 
4272
  char definer[USER_HOST_BUFF_SIZE];
 
4273
  Open_tables_state open_tables_state_backup;
 
4274
  DBUG_ENTER("fill_schema_proc");
 
4275
 
 
4276
  strxmov(definer, thd->security_ctx->priv_user, "@",
 
4277
          thd->security_ctx->priv_host, NullS);
 
4278
  /* We use this TABLE_LIST instance only for checking of privileges. */
 
4279
  bzero((char*) &proc_tables,sizeof(proc_tables));
 
4280
  proc_tables.db= (char*) "mysql";
 
4281
  proc_tables.db_length= 5;
 
4282
  proc_tables.table_name= proc_tables.alias= (char*) "proc";
 
4283
  proc_tables.table_name_length= 4;
 
4284
  proc_tables.lock_type= TL_READ;
 
4285
  full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, 1, TRUE);
 
4286
  if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup)))
 
4287
  {
 
4288
    DBUG_RETURN(1);
 
4289
  }
 
4290
  proc_table->file->ha_index_init(0, 1);
 
4291
  if ((res= proc_table->file->index_first(proc_table->record[0])))
 
4292
  {
 
4293
    res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
 
4294
    goto err;
 
4295
  }
 
4296
  if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
 
4297
  {
 
4298
    res= 1;
 
4299
    goto err;
 
4300
  }
 
4301
  while (!proc_table->file->index_next(proc_table->record[0]))
 
4302
  {
 
4303
    if (store_schema_proc(thd, table, proc_table, wild, full_access, definer))
 
4304
    {
 
4305
      res= 1;
 
4306
      goto err;
 
4307
    }
 
4308
  }
 
4309
 
 
4310
err:
 
4311
  proc_table->file->ha_index_end();
 
4312
  close_system_tables(thd, &open_tables_state_backup);
 
4313
  DBUG_RETURN(res);
 
4314
}
 
4315
 
 
4316
 
 
4317
static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
 
4318
                                  TABLE *table, bool res,
 
4319
                                  LEX_STRING *db_name,
 
4320
                                  LEX_STRING *table_name)
 
4321
{
 
4322
  CHARSET_INFO *cs= system_charset_info;
 
4323
  DBUG_ENTER("get_schema_stat_record");
 
4324
  if (res)
 
4325
  {
 
4326
    if (thd->lex->sql_command != SQLCOM_SHOW_KEYS)
 
4327
    {
 
4328
      /*
 
4329
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
 
4330
        rather than in SHOW KEYS
 
4331
      */
 
4332
      if (thd->is_error())
 
4333
        push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
4334
                     thd->main_da.sql_errno(), thd->main_da.message());
 
4335
      thd->clear_error();
 
4336
      res= 0;
 
4337
    }
 
4338
    DBUG_RETURN(res);
 
4339
  }
 
4340
  else if (!tables->view)
 
4341
  {
 
4342
    TABLE *show_table= tables->table;
 
4343
    KEY *key_info=show_table->s->key_info;
 
4344
    if (show_table->file)
 
4345
      show_table->file->info(HA_STATUS_VARIABLE |
 
4346
                             HA_STATUS_NO_LOCK |
 
4347
                             HA_STATUS_TIME);
 
4348
    for (uint i=0 ; i < show_table->s->keys ; i++,key_info++)
 
4349
    {
 
4350
      KEY_PART_INFO *key_part= key_info->key_part;
 
4351
      const char *str;
 
4352
      for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
 
4353
      {
 
4354
        restore_record(table, s->default_values);
 
4355
        table->field[1]->store(db_name->str, db_name->length, cs);
 
4356
        table->field[2]->store(table_name->str, table_name->length, cs);
 
4357
        table->field[3]->store((longlong) ((key_info->flags &
 
4358
                                            HA_NOSAME) ? 0 : 1), TRUE);
 
4359
        table->field[4]->store(db_name->str, db_name->length, cs);
 
4360
        table->field[5]->store(key_info->name, strlen(key_info->name), cs);
 
4361
        table->field[6]->store((longlong) (j+1), TRUE);
 
4362
        str=(key_part->field ? key_part->field->field_name :
 
4363
             "?unknown field?");
 
4364
        table->field[7]->store(str, strlen(str), cs);
 
4365
        if (show_table->file)
 
4366
        {
 
4367
          if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
 
4368
          {
 
4369
            table->field[8]->store(((key_part->key_part_flag &
 
4370
                                     HA_REVERSE_SORT) ?
 
4371
                                    "D" : "A"), 1, cs);
 
4372
            table->field[8]->set_notnull();
 
4373
          }
 
4374
          KEY *key=show_table->key_info+i;
 
4375
          if (key->rec_per_key[j])
 
4376
          {
 
4377
            ha_rows records=(show_table->file->stats.records /
 
4378
                             key->rec_per_key[j]);
 
4379
            table->field[9]->store((longlong) records, TRUE);
 
4380
            table->field[9]->set_notnull();
 
4381
          }
 
4382
          str= show_table->file->index_type(i);
 
4383
          table->field[13]->store(str, strlen(str), cs);
 
4384
        }
 
4385
        if (!(key_info->flags & HA_FULLTEXT) &&
 
4386
            (key_part->field &&
 
4387
             key_part->length !=
 
4388
             show_table->s->field[key_part->fieldnr-1]->key_length()))
 
4389
        {
 
4390
          table->field[10]->store((longlong) key_part->length /
 
4391
                                  key_part->field->charset()->mbmaxlen, TRUE);
 
4392
          table->field[10]->set_notnull();
 
4393
        }
 
4394
        uint flags= key_part->field ? key_part->field->flags : 0;
 
4395
        const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
 
4396
        table->field[12]->store(pos, strlen(pos), cs);
 
4397
        if (!show_table->s->keys_in_use.is_set(i))
 
4398
          table->field[14]->store(STRING_WITH_LEN("disabled"), cs);
 
4399
        else
 
4400
          table->field[14]->store("", 0, cs);
 
4401
        table->field[14]->set_notnull();
 
4402
        if (schema_table_store_record(thd, table))
 
4403
          DBUG_RETURN(1);
 
4404
      }
 
4405
    }
 
4406
  }
 
4407
  DBUG_RETURN(res);
 
4408
}
 
4409
 
 
4410
 
 
4411
static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
 
4412
                                   TABLE *table, bool res,
 
4413
                                   LEX_STRING *db_name,
 
4414
                                   LEX_STRING *table_name)
 
4415
{
 
4416
  CHARSET_INFO *cs= system_charset_info;
 
4417
  DBUG_ENTER("get_schema_views_record");
 
4418
  LEX_STRING *tmp_db_name, *tmp_table_name;
 
4419
  char definer[USER_HOST_BUFF_SIZE];
 
4420
  uint definer_len;
 
4421
  bool updatable_view;
 
4422
  /*
 
4423
    if SELECT FROM I_S.VIEWS uses only fields
 
4424
    which have OPEN_FRM_ONLY flag then 'tables'
 
4425
    structure is zeroed and only tables->view is set.
 
4426
    (see fill_schema_table_from_frm() function).
 
4427
    So we should disable other fields filling.
 
4428
  */
 
4429
  bool only_share= !tables->definer.user.str;
 
4430
 
 
4431
  if (tables->view)
 
4432
  {
 
4433
    Security_context *sctx= thd->security_ctx;
 
4434
    if (!only_share && !tables->allowed_show)
 
4435
    {
 
4436
      if (!my_strcasecmp(system_charset_info, tables->definer.user.str,
 
4437
                         sctx->priv_user) &&
 
4438
          !my_strcasecmp(system_charset_info, tables->definer.host.str,
 
4439
                         sctx->priv_host))
 
4440
        tables->allowed_show= TRUE;
 
4441
#ifndef NO_EMBEDDED_ACCESS_CHECKS
 
4442
      else
 
4443
      {
 
4444
        if ((thd->col_access & (SHOW_VIEW_ACL|SELECT_ACL)) ==
 
4445
            (SHOW_VIEW_ACL|SELECT_ACL))
 
4446
          tables->allowed_show= TRUE;
 
4447
        else
 
4448
        {
 
4449
          TABLE_LIST table_list;
 
4450
          uint view_access;
 
4451
          memset(&table_list, 0, sizeof(table_list));
 
4452
          table_list.db= tables->view_db.str;
 
4453
          table_list.table_name= tables->view_name.str;
 
4454
          table_list.grant.privilege= thd->col_access;
 
4455
          view_access= get_table_grant(thd, &table_list);
 
4456
          if ((view_access & (SHOW_VIEW_ACL|SELECT_ACL)) ==
 
4457
              (SHOW_VIEW_ACL|SELECT_ACL))
 
4458
            tables->allowed_show= TRUE;
 
4459
        }
 
4460
      }
 
4461
#endif
 
4462
    }
 
4463
    restore_record(table, s->default_values);
 
4464
    tmp_db_name= &tables->view_db;
 
4465
    tmp_table_name= &tables->view_name;
 
4466
    if (only_share)
 
4467
    {
 
4468
      tmp_db_name= db_name;
 
4469
      tmp_table_name= table_name;
 
4470
    }
 
4471
    table->field[1]->store(tmp_db_name->str, tmp_db_name->length, cs);
 
4472
    table->field[2]->store(tmp_table_name->str, tmp_table_name->length, cs);
 
4473
    if (!only_share)
 
4474
    {
 
4475
      if (tables->allowed_show)
 
4476
      {
 
4477
        table->field[3]->store(tables->view_body_utf8.str,
 
4478
                               tables->view_body_utf8.length,
 
4479
                               cs);
 
4480
      }
 
4481
 
 
4482
      if (tables->with_check != VIEW_CHECK_NONE)
 
4483
      {
 
4484
        if (tables->with_check == VIEW_CHECK_LOCAL)
 
4485
          table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs);
 
4486
        else
 
4487
          table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs);
 
4488
      }
 
4489
      else
 
4490
        table->field[4]->store(STRING_WITH_LEN("NONE"), cs);
 
4491
 
 
4492
      updatable_view= 0;
 
4493
      if (tables->algorithm != VIEW_ALGORITHM_TMPTABLE)
 
4494
      {
 
4495
        /*
 
4496
          We should use tables->view->select_lex.item_list here and
 
4497
          can not use Field_iterator_view because the view always uses
 
4498
          temporary algorithm during opening for I_S and
 
4499
          TABLE_LIST fields 'field_translation' & 'field_translation_end'
 
4500
          are uninitialized is this case.
 
4501
        */
 
4502
        List<Item> *fields= &tables->view->select_lex.item_list;
 
4503
        List_iterator<Item> it(*fields);
 
4504
        Item *item;
 
4505
        Item_field *field;
 
4506
        /*
 
4507
          check that at least one column in view is updatable
 
4508
        */
 
4509
        while ((item= it++))
 
4510
        {
 
4511
          if ((field= item->filed_for_view_update()) && field->field &&
 
4512
              !field->field->table->pos_in_table_list->schema_table)
 
4513
          {
 
4514
            updatable_view= 1;
 
4515
            break;
 
4516
          }
 
4517
        }
 
4518
        if (updatable_view && !tables->view->can_be_merged())
 
4519
          updatable_view= 0;
 
4520
      }
 
4521
      if (updatable_view)
 
4522
        table->field[5]->store(STRING_WITH_LEN("YES"), cs);
 
4523
      else
 
4524
        table->field[5]->store(STRING_WITH_LEN("NO"), cs);
 
4525
      definer_len= (strxmov(definer, tables->definer.user.str, "@",
 
4526
                            tables->definer.host.str, NullS) - definer);
 
4527
      table->field[6]->store(definer, definer_len, cs);
 
4528
      if (tables->view_suid)
 
4529
        table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs);
 
4530
      else
 
4531
        table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs);
 
4532
 
 
4533
      table->field[8]->store(tables->view_creation_ctx->get_client_cs()->csname,
 
4534
                             strlen(tables->view_creation_ctx->
 
4535
                                    get_client_cs()->csname), cs);
 
4536
 
 
4537
      table->field[9]->store(tables->view_creation_ctx->
 
4538
                             get_connection_cl()->name,
 
4539
                             strlen(tables->view_creation_ctx->
 
4540
                                    get_connection_cl()->name), cs);
 
4541
    }
 
4542
 
 
4543
    if (schema_table_store_record(thd, table))
 
4544
      DBUG_RETURN(1);
 
4545
    if (res && thd->is_error())
 
4546
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 
 
4547
                   thd->main_da.sql_errno(), thd->main_da.message());
 
4548
  }
 
4549
  if (res) 
 
4550
    thd->clear_error();
 
4551
  DBUG_RETURN(0);
 
4552
}
 
4553
 
 
4554
 
 
4555
bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name,
 
4556
                       LEX_STRING *table_name, const char *key_name,
 
4557
                       uint key_len, const char *con_type, uint con_len)
 
4558
{
 
4559
  CHARSET_INFO *cs= system_charset_info;
 
4560
  restore_record(table, s->default_values);
 
4561
  table->field[1]->store(db_name->str, db_name->length, cs);
 
4562
  table->field[2]->store(key_name, key_len, cs);
 
4563
  table->field[3]->store(db_name->str, db_name->length, cs);
 
4564
  table->field[4]->store(table_name->str, table_name->length, cs);
 
4565
  table->field[5]->store(con_type, con_len, cs);
 
4566
  return schema_table_store_record(thd, table);
 
4567
}
 
4568
 
 
4569
 
 
4570
static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
 
4571
                                         TABLE *table, bool res,
 
4572
                                         LEX_STRING *db_name,
 
4573
                                         LEX_STRING *table_name)
 
4574
{
 
4575
  DBUG_ENTER("get_schema_constraints_record");
 
4576
  if (res)
 
4577
  {
 
4578
    if (thd->is_error())
 
4579
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
4580
                   thd->main_da.sql_errno(), thd->main_da.message());
 
4581
    thd->clear_error();
 
4582
    DBUG_RETURN(0);
 
4583
  }
 
4584
  else if (!tables->view)
 
4585
  {
 
4586
    List<FOREIGN_KEY_INFO> f_key_list;
 
4587
    TABLE *show_table= tables->table;
 
4588
    KEY *key_info=show_table->key_info;
 
4589
    uint primary_key= show_table->s->primary_key;
 
4590
    show_table->file->info(HA_STATUS_VARIABLE | 
 
4591
                           HA_STATUS_NO_LOCK |
 
4592
                           HA_STATUS_TIME);
 
4593
    for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
 
4594
    {
 
4595
      if (i != primary_key && !(key_info->flags & HA_NOSAME))
 
4596
        continue;
 
4597
 
 
4598
      if (i == primary_key && !strcmp(key_info->name, primary_key_name))
 
4599
      {
 
4600
        if (store_constraints(thd, table, db_name, table_name, key_info->name,
 
4601
                              strlen(key_info->name),
 
4602
                              STRING_WITH_LEN("PRIMARY KEY")))
 
4603
          DBUG_RETURN(1);
 
4604
      }
 
4605
      else if (key_info->flags & HA_NOSAME)
 
4606
      {
 
4607
        if (store_constraints(thd, table, db_name, table_name, key_info->name,
 
4608
                              strlen(key_info->name),
 
4609
                              STRING_WITH_LEN("UNIQUE")))
 
4610
          DBUG_RETURN(1);
 
4611
      }
 
4612
    }
 
4613
 
 
4614
    show_table->file->get_foreign_key_list(thd, &f_key_list);
 
4615
    FOREIGN_KEY_INFO *f_key_info;
 
4616
    List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
 
4617
    while ((f_key_info=it++))
 
4618
    {
 
4619
      if (store_constraints(thd, table, db_name, table_name, 
 
4620
                            f_key_info->forein_id->str,
 
4621
                            strlen(f_key_info->forein_id->str),
 
4622
                            "FOREIGN KEY", 11))
 
4623
        DBUG_RETURN(1);
 
4624
    }
 
4625
  }
 
4626
  DBUG_RETURN(res);
 
4627
}
 
4628
 
 
4629
 
 
4630
static bool store_trigger(THD *thd, TABLE *table, LEX_STRING *db_name,
 
4631
                          LEX_STRING *table_name, LEX_STRING *trigger_name,
 
4632
                          enum trg_event_type event,
 
4633
                          enum trg_action_time_type timing,
 
4634
                          LEX_STRING *trigger_stmt,
 
4635
                          ulong sql_mode,
 
4636
                          LEX_STRING *definer_buffer,
 
4637
                          LEX_STRING *client_cs_name,
 
4638
                          LEX_STRING *connection_cl_name,
 
4639
                          LEX_STRING *db_cl_name)
 
4640
{
 
4641
  CHARSET_INFO *cs= system_charset_info;
 
4642
  LEX_STRING sql_mode_rep;
 
4643
 
 
4644
  restore_record(table, s->default_values);
 
4645
  table->field[1]->store(db_name->str, db_name->length, cs);
 
4646
  table->field[2]->store(trigger_name->str, trigger_name->length, cs);
 
4647
  table->field[3]->store(trg_event_type_names[event].str,
 
4648
                         trg_event_type_names[event].length, cs);
 
4649
  table->field[5]->store(db_name->str, db_name->length, cs);
 
4650
  table->field[6]->store(table_name->str, table_name->length, cs);
 
4651
  table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs);
 
4652
  table->field[10]->store(STRING_WITH_LEN("ROW"), cs);
 
4653
  table->field[11]->store(trg_action_time_type_names[timing].str,
 
4654
                          trg_action_time_type_names[timing].length, cs);
 
4655
  table->field[14]->store(STRING_WITH_LEN("OLD"), cs);
 
4656
  table->field[15]->store(STRING_WITH_LEN("NEW"), cs);
 
4657
 
 
4658
  sys_var_thd_sql_mode::symbolic_mode_representation(thd, sql_mode,
 
4659
                                                     &sql_mode_rep);
 
4660
  table->field[17]->store(sql_mode_rep.str, sql_mode_rep.length, cs);
 
4661
  table->field[18]->store(definer_buffer->str, definer_buffer->length, cs);
 
4662
  table->field[19]->store(client_cs_name->str, client_cs_name->length, cs);
 
4663
  table->field[20]->store(connection_cl_name->str,
 
4664
                          connection_cl_name->length, cs);
 
4665
  table->field[21]->store(db_cl_name->str, db_cl_name->length, cs);
 
4666
 
 
4667
  return schema_table_store_record(thd, table);
 
4668
}
 
4669
 
 
4670
 
 
4671
static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables,
 
4672
                                      TABLE *table, bool res,
 
4673
                                      LEX_STRING *db_name,
 
4674
                                      LEX_STRING *table_name)
 
4675
{
 
4676
  DBUG_ENTER("get_schema_triggers_record");
 
4677
  /*
 
4678
    res can be non zero value when processed table is a view or
 
4679
    error happened during opening of processed table.
 
4680
  */
 
4681
  if (res)
 
4682
  {
 
4683
    if (thd->is_error())
 
4684
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
4685
                   thd->main_da.sql_errno(), thd->main_da.message());
 
4686
    thd->clear_error();
 
4687
    DBUG_RETURN(0);
 
4688
  }
 
4689
  if (!tables->view && tables->table->triggers)
 
4690
  {
 
4691
    Table_triggers_list *triggers= tables->table->triggers;
 
4692
    int event, timing;
 
4693
 
 
4694
    if (check_table_access(thd, TRIGGER_ACL, tables, 1, TRUE))
 
4695
      goto ret;
 
4696
 
 
4697
    for (event= 0; event < (int)TRG_EVENT_MAX; event++)
 
4698
    {
 
4699
      for (timing= 0; timing < (int)TRG_ACTION_MAX; timing++)
 
4700
      {
 
4701
        LEX_STRING trigger_name;
 
4702
        LEX_STRING trigger_stmt;
 
4703
        ulong sql_mode;
 
4704
        char definer_holder[USER_HOST_BUFF_SIZE];
 
4705
        LEX_STRING definer_buffer;
 
4706
        LEX_STRING client_cs_name;
 
4707
        LEX_STRING connection_cl_name;
 
4708
        LEX_STRING db_cl_name;
 
4709
 
 
4710
        definer_buffer.str= definer_holder;
 
4711
        if (triggers->get_trigger_info(thd, (enum trg_event_type) event,
 
4712
                                       (enum trg_action_time_type)timing,
 
4713
                                       &trigger_name, &trigger_stmt,
 
4714
                                       &sql_mode,
 
4715
                                       &definer_buffer,
 
4716
                                       &client_cs_name,
 
4717
                                       &connection_cl_name,
 
4718
                                       &db_cl_name))
 
4719
          continue;
 
4720
 
 
4721
        if (store_trigger(thd, table, db_name, table_name, &trigger_name,
 
4722
                         (enum trg_event_type) event,
 
4723
                         (enum trg_action_time_type) timing, &trigger_stmt,
 
4724
                         sql_mode,
 
4725
                         &definer_buffer,
 
4726
                         &client_cs_name,
 
4727
                         &connection_cl_name,
 
4728
                         &db_cl_name))
 
4729
          DBUG_RETURN(1);
 
4730
      }
 
4731
    }
 
4732
  }
 
4733
ret:
 
4734
  DBUG_RETURN(0);
 
4735
}
 
4736
 
 
4737
 
 
4738
void store_key_column_usage(TABLE *table, LEX_STRING *db_name,
 
4739
                            LEX_STRING *table_name, const char *key_name,
 
4740
                            uint key_len, const char *con_type, uint con_len,
 
4741
                            longlong idx)
 
4742
{
 
4743
  CHARSET_INFO *cs= system_charset_info;
 
4744
  table->field[1]->store(db_name->str, db_name->length, cs);
 
4745
  table->field[2]->store(key_name, key_len, cs);
 
4746
  table->field[4]->store(db_name->str, db_name->length, cs);
 
4747
  table->field[5]->store(table_name->str, table_name->length, cs);
 
4748
  table->field[6]->store(con_type, con_len, cs);
 
4749
  table->field[7]->store((longlong) idx, TRUE);
 
4750
}
 
4751
 
 
4752
 
 
4753
static int get_schema_key_column_usage_record(THD *thd,
 
4754
                                              TABLE_LIST *tables,
 
4755
                                              TABLE *table, bool res,
 
4756
                                              LEX_STRING *db_name,
 
4757
                                              LEX_STRING *table_name)
 
4758
{
 
4759
  DBUG_ENTER("get_schema_key_column_usage_record");
 
4760
  if (res)
 
4761
  {
 
4762
    if (thd->is_error())
 
4763
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
4764
                   thd->main_da.sql_errno(), thd->main_da.message());
 
4765
    thd->clear_error();
 
4766
    DBUG_RETURN(0);
 
4767
  }
 
4768
  else if (!tables->view)
 
4769
  {
 
4770
    List<FOREIGN_KEY_INFO> f_key_list;
 
4771
    TABLE *show_table= tables->table;
 
4772
    KEY *key_info=show_table->key_info;
 
4773
    uint primary_key= show_table->s->primary_key;
 
4774
    show_table->file->info(HA_STATUS_VARIABLE | 
 
4775
                           HA_STATUS_NO_LOCK |
 
4776
                           HA_STATUS_TIME);
 
4777
    for (uint i=0 ; i < show_table->s->keys ; i++, key_info++)
 
4778
    {
 
4779
      if (i != primary_key && !(key_info->flags & HA_NOSAME))
 
4780
        continue;
 
4781
      uint f_idx= 0;
 
4782
      KEY_PART_INFO *key_part= key_info->key_part;
 
4783
      for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
 
4784
      {
 
4785
        if (key_part->field)
 
4786
        {
 
4787
          f_idx++;
 
4788
          restore_record(table, s->default_values);
 
4789
          store_key_column_usage(table, db_name, table_name,
 
4790
                                 key_info->name,
 
4791
                                 strlen(key_info->name), 
 
4792
                                 key_part->field->field_name, 
 
4793
                                 strlen(key_part->field->field_name),
 
4794
                                 (longlong) f_idx);
 
4795
          if (schema_table_store_record(thd, table))
 
4796
            DBUG_RETURN(1);
 
4797
        }
 
4798
      }
 
4799
    }
 
4800
 
 
4801
    show_table->file->get_foreign_key_list(thd, &f_key_list);
 
4802
    FOREIGN_KEY_INFO *f_key_info;
 
4803
    List_iterator_fast<FOREIGN_KEY_INFO> fkey_it(f_key_list);
 
4804
    while ((f_key_info= fkey_it++))
 
4805
    {
 
4806
      LEX_STRING *f_info;
 
4807
      LEX_STRING *r_info;
 
4808
      List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields),
 
4809
        it1(f_key_info->referenced_fields);
 
4810
      uint f_idx= 0;
 
4811
      while ((f_info= it++))
 
4812
      {
 
4813
        r_info= it1++;
 
4814
        f_idx++;
 
4815
        restore_record(table, s->default_values);
 
4816
        store_key_column_usage(table, db_name, table_name,
 
4817
                               f_key_info->forein_id->str,
 
4818
                               f_key_info->forein_id->length,
 
4819
                               f_info->str, f_info->length,
 
4820
                               (longlong) f_idx);
 
4821
        table->field[8]->store((longlong) f_idx, TRUE);
 
4822
        table->field[8]->set_notnull();
 
4823
        table->field[9]->store(f_key_info->referenced_db->str,
 
4824
                               f_key_info->referenced_db->length,
 
4825
                               system_charset_info);
 
4826
        table->field[9]->set_notnull();
 
4827
        table->field[10]->store(f_key_info->referenced_table->str,
 
4828
                                f_key_info->referenced_table->length, 
 
4829
                                system_charset_info);
 
4830
        table->field[10]->set_notnull();
 
4831
        table->field[11]->store(r_info->str, r_info->length,
 
4832
                                system_charset_info);
 
4833
        table->field[11]->set_notnull();
 
4834
        if (schema_table_store_record(thd, table))
 
4835
          DBUG_RETURN(1);
 
4836
      }
 
4837
    }
 
4838
  }
 
4839
  DBUG_RETURN(res);
 
4840
}
 
4841
 
 
4842
 
 
4843
#ifdef WITH_PARTITION_STORAGE_ENGINE
 
4844
static void collect_partition_expr(List<char> &field_list, String *str)
 
4845
{
 
4846
  List_iterator<char> part_it(field_list);
 
4847
  ulong no_fields= field_list.elements;
 
4848
  const char *field_str;
 
4849
  str->length(0);
 
4850
  while ((field_str= part_it++))
 
4851
  {
 
4852
    str->append(field_str);
 
4853
    if (--no_fields != 0)
 
4854
      str->append(",");
 
4855
  }
 
4856
  return;
 
4857
}
 
4858
#endif
 
4859
 
 
4860
 
 
4861
static void store_schema_partitions_record(THD *thd, TABLE *schema_table,
 
4862
                                           TABLE *showing_table,
 
4863
                                           partition_element *part_elem,
 
4864
                                           handler *file, uint part_id)
 
4865
{
 
4866
  TABLE* table= schema_table;
 
4867
  CHARSET_INFO *cs= system_charset_info;
 
4868
  PARTITION_INFO stat_info;
 
4869
  MYSQL_TIME time;
 
4870
  file->get_dynamic_partition_info(&stat_info, part_id);
 
4871
  table->field[12]->store((longlong) stat_info.records, TRUE);
 
4872
  table->field[13]->store((longlong) stat_info.mean_rec_length, TRUE);
 
4873
  table->field[14]->store((longlong) stat_info.data_file_length, TRUE);
 
4874
  if (stat_info.max_data_file_length)
 
4875
  {
 
4876
    table->field[15]->store((longlong) stat_info.max_data_file_length, TRUE);
 
4877
    table->field[15]->set_notnull();
 
4878
  }
 
4879
  table->field[16]->store((longlong) stat_info.index_file_length, TRUE);
 
4880
  table->field[17]->store((longlong) stat_info.delete_length, TRUE);
 
4881
  if (stat_info.create_time)
 
4882
  {
 
4883
    thd->variables.time_zone->gmt_sec_to_TIME(&time,
 
4884
                                              (my_time_t)stat_info.create_time);
 
4885
    table->field[18]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
4886
    table->field[18]->set_notnull();
 
4887
  }
 
4888
  if (stat_info.update_time)
 
4889
  {
 
4890
    thd->variables.time_zone->gmt_sec_to_TIME(&time,
 
4891
                                              (my_time_t)stat_info.update_time);
 
4892
    table->field[19]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
4893
    table->field[19]->set_notnull();
 
4894
  }
 
4895
  if (stat_info.check_time)
 
4896
  {
 
4897
    thd->variables.time_zone->gmt_sec_to_TIME(&time,
 
4898
                                              (my_time_t)stat_info.check_time);
 
4899
    table->field[20]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
4900
    table->field[20]->set_notnull();
 
4901
  }
 
4902
  if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
 
4903
  {
 
4904
    table->field[21]->store((longlong) stat_info.check_sum, TRUE);
 
4905
    table->field[21]->set_notnull();
 
4906
  }
 
4907
  if (part_elem)
 
4908
  {
 
4909
    if (part_elem->part_comment)
 
4910
      table->field[22]->store(part_elem->part_comment,
 
4911
                              strlen(part_elem->part_comment), cs);
 
4912
    else
 
4913
      table->field[22]->store(STRING_WITH_LEN(""), cs);
 
4914
    if (part_elem->nodegroup_id != UNDEF_NODEGROUP)
 
4915
      table->field[23]->store((longlong) part_elem->nodegroup_id, TRUE);
 
4916
    else
 
4917
      table->field[23]->store(STRING_WITH_LEN("default"), cs);
 
4918
 
 
4919
    table->field[24]->set_notnull();
 
4920
    if (part_elem->tablespace_name)
 
4921
      table->field[24]->store(part_elem->tablespace_name,
 
4922
                              strlen(part_elem->tablespace_name), cs);
 
4923
    else
 
4924
    {
 
4925
      char *ts= showing_table->file->get_tablespace_name(thd,0,0);
 
4926
      if(ts)
 
4927
      {
 
4928
        table->field[24]->store(ts, strlen(ts), cs);
 
4929
        my_free(ts, MYF(0));
 
4930
      }
 
4931
      else
 
4932
        table->field[24]->set_null();
 
4933
    }
 
4934
  }
 
4935
  return;
 
4936
}
 
4937
 
 
4938
 
 
4939
static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
 
4940
                                        TABLE *table, bool res,
 
4941
                                        LEX_STRING *db_name,
 
4942
                                        LEX_STRING *table_name)
 
4943
{
 
4944
  CHARSET_INFO *cs= system_charset_info;
 
4945
  char buff[61];
 
4946
  String tmp_res(buff, sizeof(buff), cs);
 
4947
  String tmp_str;
 
4948
  TABLE *show_table= tables->table;
 
4949
  handler *file;
 
4950
#ifdef WITH_PARTITION_STORAGE_ENGINE
 
4951
  partition_info *part_info;
 
4952
#endif
 
4953
  DBUG_ENTER("get_schema_partitions_record");
 
4954
 
 
4955
  if (res)
 
4956
  {
 
4957
    if (thd->is_error())
 
4958
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
4959
                   thd->main_da.sql_errno(), thd->main_da.message());
 
4960
    thd->clear_error();
 
4961
    DBUG_RETURN(0);
 
4962
  }
 
4963
  file= show_table->file;
 
4964
#ifdef WITH_PARTITION_STORAGE_ENGINE
 
4965
  part_info= show_table->part_info;
 
4966
  if (part_info)
 
4967
  {
 
4968
    partition_element *part_elem;
 
4969
    List_iterator<partition_element> part_it(part_info->partitions);
 
4970
    uint part_pos= 0, part_id= 0;
 
4971
 
 
4972
    restore_record(table, s->default_values);
 
4973
    table->field[1]->store(db_name->str, db_name->length, cs);
 
4974
    table->field[2]->store(table_name->str, table_name->length, cs);
 
4975
 
 
4976
 
 
4977
    /* Partition method*/
 
4978
    switch (part_info->part_type) {
 
4979
    case RANGE_PARTITION:
 
4980
      table->field[7]->store(partition_keywords[PKW_RANGE].str,
 
4981
                             partition_keywords[PKW_RANGE].length, cs);
 
4982
      break;
 
4983
    case LIST_PARTITION:
 
4984
      table->field[7]->store(partition_keywords[PKW_LIST].str,
 
4985
                             partition_keywords[PKW_LIST].length, cs);
 
4986
      break;
 
4987
    case HASH_PARTITION:
 
4988
      tmp_res.length(0);
 
4989
      if (part_info->linear_hash_ind)
 
4990
        tmp_res.append(partition_keywords[PKW_LINEAR].str,
 
4991
                       partition_keywords[PKW_LINEAR].length);
 
4992
      if (part_info->list_of_part_fields)
 
4993
        tmp_res.append(partition_keywords[PKW_KEY].str,
 
4994
                       partition_keywords[PKW_KEY].length);
 
4995
      else
 
4996
        tmp_res.append(partition_keywords[PKW_HASH].str, 
 
4997
                       partition_keywords[PKW_HASH].length);
 
4998
      table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs);
 
4999
      break;
 
5000
    default:
 
5001
      DBUG_ASSERT(0);
 
5002
      my_error(ER_OUT_OF_RESOURCES, MYF(0));
 
5003
      current_thd->fatal_error();
 
5004
      DBUG_RETURN(1);
 
5005
    }
 
5006
    table->field[7]->set_notnull();
 
5007
 
 
5008
    /* Partition expression */
 
5009
    if (part_info->part_expr)
 
5010
    {
 
5011
      table->field[9]->store(part_info->part_func_string,
 
5012
                             part_info->part_func_len, cs);
 
5013
    }
 
5014
    else if (part_info->list_of_part_fields)
 
5015
    {
 
5016
      collect_partition_expr(part_info->part_field_list, &tmp_str);
 
5017
      table->field[9]->store(tmp_str.ptr(), tmp_str.length(), cs);
 
5018
    }
 
5019
    table->field[9]->set_notnull();
 
5020
 
 
5021
    if (part_info->is_sub_partitioned())
 
5022
    {
 
5023
      /* Subpartition method */
 
5024
      tmp_res.length(0);
 
5025
      if (part_info->linear_hash_ind)
 
5026
        tmp_res.append(partition_keywords[PKW_LINEAR].str,
 
5027
                       partition_keywords[PKW_LINEAR].length);
 
5028
      if (part_info->list_of_subpart_fields)
 
5029
        tmp_res.append(partition_keywords[PKW_KEY].str,
 
5030
                       partition_keywords[PKW_KEY].length);
 
5031
      else
 
5032
        tmp_res.append(partition_keywords[PKW_HASH].str, 
 
5033
                       partition_keywords[PKW_HASH].length);
 
5034
      table->field[8]->store(tmp_res.ptr(), tmp_res.length(), cs);
 
5035
      table->field[8]->set_notnull();
 
5036
 
 
5037
      /* Subpartition expression */
 
5038
      if (part_info->subpart_expr)
 
5039
      {
 
5040
        table->field[10]->store(part_info->subpart_func_string,
 
5041
                                part_info->subpart_func_len, cs);
 
5042
      }
 
5043
      else if (part_info->list_of_subpart_fields)
 
5044
      {
 
5045
        collect_partition_expr(part_info->subpart_field_list, &tmp_str);
 
5046
        table->field[10]->store(tmp_str.ptr(), tmp_str.length(), cs);
 
5047
      }
 
5048
      table->field[10]->set_notnull();
 
5049
    }
 
5050
 
 
5051
    while ((part_elem= part_it++))
 
5052
    {
 
5053
      table->field[3]->store(part_elem->partition_name,
 
5054
                             strlen(part_elem->partition_name), cs);
 
5055
      table->field[3]->set_notnull();
 
5056
      /* PARTITION_ORDINAL_POSITION */
 
5057
      table->field[5]->store((longlong) ++part_pos, TRUE);
 
5058
      table->field[5]->set_notnull();
 
5059
 
 
5060
      /* Partition description */
 
5061
      if (part_info->part_type == RANGE_PARTITION)
 
5062
      {
 
5063
        if (part_elem->range_value != LONGLONG_MAX)
 
5064
          table->field[11]->store((longlong) part_elem->range_value, FALSE);
 
5065
        else
 
5066
          table->field[11]->store(partition_keywords[PKW_MAXVALUE].str,
 
5067
                                 partition_keywords[PKW_MAXVALUE].length, cs);
 
5068
        table->field[11]->set_notnull();
 
5069
      }
 
5070
      else if (part_info->part_type == LIST_PARTITION)
 
5071
      {
 
5072
        List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
 
5073
        part_elem_value *list_value;
 
5074
        uint no_items= part_elem->list_val_list.elements;
 
5075
        tmp_str.length(0);
 
5076
        tmp_res.length(0);
 
5077
        if (part_elem->has_null_value)
 
5078
        {
 
5079
          tmp_str.append("NULL");
 
5080
          if (no_items > 0)
 
5081
            tmp_str.append(",");
 
5082
        }
 
5083
        while ((list_value= list_val_it++))
 
5084
        {
 
5085
          if (!list_value->unsigned_flag)
 
5086
            tmp_res.set(list_value->value, cs);
 
5087
          else
 
5088
            tmp_res.set((ulonglong)list_value->value, cs);
 
5089
          tmp_str.append(tmp_res);
 
5090
          if (--no_items != 0)
 
5091
            tmp_str.append(",");
 
5092
        };
 
5093
        table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs);
 
5094
        table->field[11]->set_notnull();
 
5095
      }
 
5096
 
 
5097
      if (part_elem->subpartitions.elements)
 
5098
      {
 
5099
        List_iterator<partition_element> sub_it(part_elem->subpartitions);
 
5100
        partition_element *subpart_elem;
 
5101
        uint subpart_pos= 0;
 
5102
 
 
5103
        while ((subpart_elem= sub_it++))
 
5104
        {
 
5105
          table->field[4]->store(subpart_elem->partition_name,
 
5106
                                 strlen(subpart_elem->partition_name), cs);
 
5107
          table->field[4]->set_notnull();
 
5108
          /* SUBPARTITION_ORDINAL_POSITION */
 
5109
          table->field[6]->store((longlong) ++subpart_pos, TRUE);
 
5110
          table->field[6]->set_notnull();
 
5111
          
 
5112
          store_schema_partitions_record(thd, table, show_table, subpart_elem,
 
5113
                                         file, part_id);
 
5114
          part_id++;
 
5115
          if(schema_table_store_record(thd, table))
 
5116
            DBUG_RETURN(1);
 
5117
        }
 
5118
      }
 
5119
      else
 
5120
      {
 
5121
        store_schema_partitions_record(thd, table, show_table, part_elem,
 
5122
                                       file, part_id);
 
5123
        part_id++;
 
5124
        if(schema_table_store_record(thd, table))
 
5125
          DBUG_RETURN(1);
 
5126
      }
 
5127
    }
 
5128
    DBUG_RETURN(0);
 
5129
  }
 
5130
  else
 
5131
#endif
 
5132
  {
 
5133
    store_schema_partitions_record(thd, table, show_table, 0, file, 0);
 
5134
    if(schema_table_store_record(thd, table))
 
5135
      DBUG_RETURN(1);
 
5136
  }
 
5137
  DBUG_RETURN(0);
 
5138
}
 
5139
 
 
5140
 
 
5141
#ifdef NOT_USED
 
5142
static interval_type get_real_interval_type(interval_type i_type)
 
5143
{
 
5144
  switch (i_type) {
 
5145
  case INTERVAL_YEAR:
 
5146
    return INTERVAL_YEAR;
 
5147
 
 
5148
  case INTERVAL_QUARTER:
 
5149
  case INTERVAL_YEAR_MONTH:
 
5150
  case INTERVAL_MONTH:
 
5151
    return INTERVAL_MONTH;
 
5152
 
 
5153
  case INTERVAL_WEEK:
 
5154
  case INTERVAL_DAY:
 
5155
    return INTERVAL_DAY;
 
5156
 
 
5157
  case INTERVAL_DAY_HOUR:
 
5158
  case INTERVAL_HOUR:
 
5159
    return INTERVAL_HOUR;
 
5160
 
 
5161
  case INTERVAL_DAY_MINUTE:
 
5162
  case INTERVAL_HOUR_MINUTE:
 
5163
  case INTERVAL_MINUTE:
 
5164
    return INTERVAL_MINUTE;
 
5165
 
 
5166
  case INTERVAL_DAY_SECOND:
 
5167
  case INTERVAL_HOUR_SECOND:
 
5168
  case INTERVAL_MINUTE_SECOND:
 
5169
  case INTERVAL_SECOND:
 
5170
    return INTERVAL_SECOND;
 
5171
 
 
5172
  case INTERVAL_DAY_MICROSECOND:
 
5173
  case INTERVAL_HOUR_MICROSECOND:
 
5174
  case INTERVAL_MINUTE_MICROSECOND:
 
5175
  case INTERVAL_SECOND_MICROSECOND:
 
5176
  case INTERVAL_MICROSECOND:
 
5177
    return INTERVAL_MICROSECOND;
 
5178
  case INTERVAL_LAST:
 
5179
    DBUG_ASSERT(0);
 
5180
  }
 
5181
  DBUG_ASSERT(0);
 
5182
  return INTERVAL_SECOND;
 
5183
}
 
5184
 
 
5185
#endif
 
5186
 
 
5187
#ifdef HAVE_EVENT_SCHEDULER
 
5188
/*
 
5189
  Loads an event from mysql.event and copies it's data to a row of
 
5190
  I_S.EVENTS
 
5191
 
 
5192
  Synopsis
 
5193
    copy_event_to_schema_table()
 
5194
      thd         Thread
 
5195
      sch_table   The schema table (information_schema.event)
 
5196
      event_table The event table to use for loading (mysql.event).
 
5197
 
 
5198
  Returns
 
5199
    0  OK
 
5200
    1  Error
 
5201
*/
 
5202
 
 
5203
int
 
5204
copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
 
5205
{
 
5206
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
 
5207
  CHARSET_INFO *scs= system_charset_info;
 
5208
  MYSQL_TIME time;
 
5209
  Event_timed et;
 
5210
  DBUG_ENTER("copy_event_to_schema_table");
 
5211
 
 
5212
  restore_record(sch_table, s->default_values);
 
5213
 
 
5214
  if (et.load_from_row(thd, event_table))
 
5215
  {
 
5216
    my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), event_table->alias);
 
5217
    DBUG_RETURN(1);
 
5218
  }
 
5219
 
 
5220
  if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0)))
 
5221
    DBUG_RETURN(0);
 
5222
 
 
5223
  /*
 
5224
    Skip events in schemas one does not have access to. The check is
 
5225
    optimized. It's guaranteed in case of SHOW EVENTS that the user
 
5226
    has access.
 
5227
  */
 
5228
  if (thd->lex->sql_command != SQLCOM_SHOW_EVENTS &&
 
5229
      check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1,
 
5230
                   is_schema_db(et.dbname.str, et.dbname.length)))
 
5231
    DBUG_RETURN(0);
 
5232
 
 
5233
  /* ->field[0] is EVENT_CATALOG and is by default NULL */
 
5234
 
 
5235
  sch_table->field[ISE_EVENT_SCHEMA]->
 
5236
                                store(et.dbname.str, et.dbname.length,scs);
 
5237
  sch_table->field[ISE_EVENT_NAME]->
 
5238
                                store(et.name.str, et.name.length, scs);
 
5239
  sch_table->field[ISE_DEFINER]->
 
5240
                                store(et.definer.str, et.definer.length, scs);
 
5241
  const String *tz_name= et.time_zone->get_name();
 
5242
  sch_table->field[ISE_TIME_ZONE]->
 
5243
                                store(tz_name->ptr(), tz_name->length(), scs);
 
5244
  sch_table->field[ISE_EVENT_BODY]->
 
5245
                                store(STRING_WITH_LEN("SQL"), scs);
 
5246
  sch_table->field[ISE_EVENT_DEFINITION]->store(
 
5247
    et.body_utf8.str, et.body_utf8.length, scs);
 
5248
 
 
5249
  /* SQL_MODE */
 
5250
  {
 
5251
    LEX_STRING sql_mode;
 
5252
    sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
 
5253
                                                       &sql_mode);
 
5254
    sch_table->field[ISE_SQL_MODE]->
 
5255
                                store(sql_mode.str, sql_mode.length, scs);
 
5256
  }
 
5257
 
 
5258
  int not_used=0;
 
5259
 
 
5260
  if (et.expression)
 
5261
  {
 
5262
    String show_str;
 
5263
    /* type */
 
5264
    sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("RECURRING"), scs);
 
5265
 
 
5266
    if (Events::reconstruct_interval_expression(&show_str, et.interval,
 
5267
                                                et.expression))
 
5268
      DBUG_RETURN(1);
 
5269
 
 
5270
    sch_table->field[ISE_INTERVAL_VALUE]->set_notnull();
 
5271
    sch_table->field[ISE_INTERVAL_VALUE]->
 
5272
                                store(show_str.ptr(), show_str.length(), scs);
 
5273
 
 
5274
    LEX_STRING *ival= &interval_type_to_name[et.interval];
 
5275
    sch_table->field[ISE_INTERVAL_FIELD]->set_notnull();
 
5276
    sch_table->field[ISE_INTERVAL_FIELD]->store(ival->str, ival->length, scs);
 
5277
 
 
5278
    /* starts & ends . STARTS is always set - see sql_yacc.yy */
 
5279
    et.time_zone->gmt_sec_to_TIME(&time, et.starts);
 
5280
    sch_table->field[ISE_STARTS]->set_notnull();
 
5281
    sch_table->field[ISE_STARTS]->
 
5282
                                store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
5283
 
 
5284
    if (!et.ends_null)
 
5285
    {
 
5286
      et.time_zone->gmt_sec_to_TIME(&time, et.ends);
 
5287
      sch_table->field[ISE_ENDS]->set_notnull();
 
5288
      sch_table->field[ISE_ENDS]->
 
5289
                                store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
5290
    }
 
5291
  }
 
5292
  else
 
5293
  {
 
5294
    /* type */
 
5295
    sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("ONE TIME"), scs);
 
5296
 
 
5297
    et.time_zone->gmt_sec_to_TIME(&time, et.execute_at);
 
5298
    sch_table->field[ISE_EXECUTE_AT]->set_notnull();
 
5299
    sch_table->field[ISE_EXECUTE_AT]->
 
5300
                          store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
5301
  }
 
5302
 
 
5303
  /* status */
 
5304
 
 
5305
  switch (et.status)
 
5306
  {
 
5307
    case Event_parse_data::ENABLED:
 
5308
      sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs);
 
5309
      break;
 
5310
    case Event_parse_data::SLAVESIDE_DISABLED:
 
5311
      sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("SLAVESIDE_DISABLED"),
 
5312
                                          scs);
 
5313
      break;
 
5314
    case Event_parse_data::DISABLED:
 
5315
      sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs);
 
5316
      break;
 
5317
    default:
 
5318
      DBUG_ASSERT(0);
 
5319
  }
 
5320
  sch_table->field[ISE_ORIGINATOR]->store(et.originator, TRUE);
 
5321
 
 
5322
  /* on_completion */
 
5323
  if (et.on_completion == Event_parse_data::ON_COMPLETION_DROP)
 
5324
    sch_table->field[ISE_ON_COMPLETION]->
 
5325
                                store(STRING_WITH_LEN("NOT PRESERVE"), scs);
 
5326
  else
 
5327
    sch_table->field[ISE_ON_COMPLETION]->
 
5328
                                store(STRING_WITH_LEN("PRESERVE"), scs);
 
5329
    
 
5330
  number_to_datetime(et.created, &time, 0, &not_used);
 
5331
  DBUG_ASSERT(not_used==0);
 
5332
  sch_table->field[ISE_CREATED]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
5333
 
 
5334
  number_to_datetime(et.modified, &time, 0, &not_used);
 
5335
  DBUG_ASSERT(not_used==0);
 
5336
  sch_table->field[ISE_LAST_ALTERED]->
 
5337
                                store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
5338
 
 
5339
  if (et.last_executed)
 
5340
  {
 
5341
    et.time_zone->gmt_sec_to_TIME(&time, et.last_executed);
 
5342
    sch_table->field[ISE_LAST_EXECUTED]->set_notnull();
 
5343
    sch_table->field[ISE_LAST_EXECUTED]->
 
5344
                       store_time(&time, MYSQL_TIMESTAMP_DATETIME);
 
5345
  }
 
5346
 
 
5347
  sch_table->field[ISE_EVENT_COMMENT]->
 
5348
                      store(et.comment.str, et.comment.length, scs);
 
5349
 
 
5350
  sch_table->field[ISE_CLIENT_CS]->set_notnull();
 
5351
  sch_table->field[ISE_CLIENT_CS]->store(
 
5352
    et.creation_ctx->get_client_cs()->csname,
 
5353
    strlen(et.creation_ctx->get_client_cs()->csname),
 
5354
    scs);
 
5355
 
 
5356
  sch_table->field[ISE_CONNECTION_CL]->set_notnull();
 
5357
  sch_table->field[ISE_CONNECTION_CL]->store(
 
5358
    et.creation_ctx->get_connection_cl()->name,
 
5359
    strlen(et.creation_ctx->get_connection_cl()->name),
 
5360
    scs);
 
5361
 
 
5362
  sch_table->field[ISE_DB_CL]->set_notnull();
 
5363
  sch_table->field[ISE_DB_CL]->store(
 
5364
    et.creation_ctx->get_db_cl()->name,
 
5365
    strlen(et.creation_ctx->get_db_cl()->name),
 
5366
    scs);
 
5367
 
 
5368
  if (schema_table_store_record(thd, sch_table))
 
5369
    DBUG_RETURN(1);
 
5370
 
 
5371
  DBUG_RETURN(0);
 
5372
}
 
5373
#endif
 
5374
 
 
5375
int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
 
5376
{
 
5377
  DBUG_ENTER("fill_open_tables");
 
5378
  const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
 
5379
  TABLE *table= tables->table;
 
5380
  CHARSET_INFO *cs= system_charset_info;
 
5381
  OPEN_TABLE_LIST *open_list;
 
5382
  if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db, wild))
 
5383
            && thd->is_fatal_error)
 
5384
    DBUG_RETURN(1);
 
5385
 
 
5386
  for (; open_list ; open_list=open_list->next)
 
5387
  {
 
5388
    restore_record(table, s->default_values);
 
5389
    table->field[0]->store(open_list->db, strlen(open_list->db), cs);
 
5390
    table->field[1]->store(open_list->table, strlen(open_list->table), cs);
 
5391
    table->field[2]->store((longlong) open_list->in_use, TRUE);
 
5392
    table->field[3]->store((longlong) open_list->locked, TRUE);
 
5393
    if (schema_table_store_record(thd, table))
 
5394
      DBUG_RETURN(1);
 
5395
  }
 
5396
  DBUG_RETURN(0);
 
5397
}
 
5398
 
 
5399
 
 
5400
int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
 
5401
{
 
5402
  DBUG_ENTER("fill_variables");
 
5403
  int res= 0;
 
5404
  LEX *lex= thd->lex;
 
5405
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
 
5406
  enum enum_schema_tables schema_table_idx=
 
5407
    get_schema_table_idx(tables->schema_table);
 
5408
  enum enum_var_type option_type= OPT_SESSION;
 
5409
  bool upper_case_names= (schema_table_idx != SCH_VARIABLES);
 
5410
  bool sorted_vars= (schema_table_idx == SCH_VARIABLES);
 
5411
 
 
5412
  if (lex->option_type == OPT_GLOBAL ||
 
5413
      schema_table_idx == SCH_GLOBAL_VARIABLES)
 
5414
    option_type= OPT_GLOBAL;
 
5415
 
 
5416
  rw_rdlock(&LOCK_system_variables_hash);
 
5417
  res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars),
 
5418
                         option_type, NULL, "", tables->table, upper_case_names, cond);
 
5419
  rw_unlock(&LOCK_system_variables_hash);
 
5420
  DBUG_RETURN(res);
 
5421
}
 
5422
 
 
5423
 
 
5424
int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
 
5425
{
 
5426
  DBUG_ENTER("fill_status");
 
5427
  LEX *lex= thd->lex;
 
5428
  const char *wild= lex->wild ? lex->wild->ptr() : NullS;
 
5429
  int res= 0;
 
5430
  STATUS_VAR *tmp1, tmp;
 
5431
  enum enum_schema_tables schema_table_idx=
 
5432
    get_schema_table_idx(tables->schema_table);
 
5433
  enum enum_var_type option_type;
 
5434
  bool upper_case_names= (schema_table_idx != SCH_STATUS);
 
5435
 
 
5436
  if (schema_table_idx == SCH_STATUS)
 
5437
  {
 
5438
    option_type= lex->option_type;
 
5439
    if (option_type == OPT_GLOBAL)
 
5440
      tmp1= &tmp;
 
5441
    else
 
5442
      tmp1= thd->initial_status_var;
 
5443
  }
 
5444
  else if (schema_table_idx == SCH_GLOBAL_STATUS)
 
5445
  {
 
5446
    option_type= OPT_GLOBAL;
 
5447
    tmp1= &tmp;
 
5448
  }
 
5449
  else
 
5450
  { 
 
5451
    option_type= OPT_SESSION;
 
5452
    tmp1= &thd->status_var;
 
5453
  }
 
5454
 
 
5455
  pthread_mutex_lock(&LOCK_status);
 
5456
  if (option_type == OPT_GLOBAL)
 
5457
    calc_sum_of_all_status(&tmp);
 
5458
  res= show_status_array(thd, wild,
 
5459
                         (SHOW_VAR *)all_status_vars.buffer,
 
5460
                         option_type, tmp1, "", tables->table,
 
5461
                         upper_case_names, cond);
 
5462
  pthread_mutex_unlock(&LOCK_status);
 
5463
  DBUG_RETURN(res);
 
5464
}
 
5465
 
 
5466
 
 
5467
/*
 
5468
  Fill and store records into I_S.referential_constraints table
 
5469
 
 
5470
  SYNOPSIS
 
5471
    get_referential_constraints_record()
 
5472
    thd                 thread handle
 
5473
    tables              table list struct(processed table)
 
5474
    table               I_S table
 
5475
    res                 1 means the error during opening of the processed table
 
5476
                        0 means processed table is opened without error
 
5477
    base_name           db name
 
5478
    file_name           table name
 
5479
 
 
5480
  RETURN
 
5481
    0   ok
 
5482
    #   error
 
5483
*/
 
5484
 
 
5485
static int
 
5486
get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
 
5487
                                   TABLE *table, bool res,
 
5488
                                   LEX_STRING *db_name, LEX_STRING *table_name)
 
5489
{
 
5490
  CHARSET_INFO *cs= system_charset_info;
 
5491
  DBUG_ENTER("get_referential_constraints_record");
 
5492
 
 
5493
  if (res)
 
5494
  {
 
5495
    if (thd->is_error())
 
5496
      push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
 
5497
                   thd->main_da.sql_errno(), thd->main_da.message());
 
5498
    thd->clear_error();
 
5499
    DBUG_RETURN(0);
 
5500
  }
 
5501
  if (!tables->view)
 
5502
  {
 
5503
    List<FOREIGN_KEY_INFO> f_key_list;
 
5504
    TABLE *show_table= tables->table;
 
5505
    show_table->file->info(HA_STATUS_VARIABLE | 
 
5506
                           HA_STATUS_NO_LOCK |
 
5507
                           HA_STATUS_TIME);
 
5508
 
 
5509
    show_table->file->get_foreign_key_list(thd, &f_key_list);
 
5510
    FOREIGN_KEY_INFO *f_key_info;
 
5511
    List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
 
5512
    while ((f_key_info= it++))
 
5513
    {
 
5514
      restore_record(table, s->default_values);
 
5515
      table->field[1]->store(db_name->str, db_name->length, cs);
 
5516
      table->field[9]->store(table_name->str, table_name->length, cs);
 
5517
      table->field[2]->store(f_key_info->forein_id->str,
 
5518
                             f_key_info->forein_id->length, cs);
 
5519
      table->field[4]->store(f_key_info->referenced_db->str, 
 
5520
                             f_key_info->referenced_db->length, cs);
 
5521
      table->field[10]->store(f_key_info->referenced_table->str, 
 
5522
                             f_key_info->referenced_table->length, cs);
 
5523
      if (f_key_info->referenced_key_name)
 
5524
      {
 
5525
        table->field[5]->store(f_key_info->referenced_key_name->str, 
 
5526
                               f_key_info->referenced_key_name->length, cs);
 
5527
        table->field[5]->set_notnull();
 
5528
      }
 
5529
      else
 
5530
        table->field[5]->set_null();
 
5531
      table->field[6]->store(STRING_WITH_LEN("NONE"), cs);
 
5532
      table->field[7]->store(f_key_info->update_method->str, 
 
5533
                             f_key_info->update_method->length, cs);
 
5534
      table->field[8]->store(f_key_info->delete_method->str, 
 
5535
                             f_key_info->delete_method->length, cs);
 
5536
      if (schema_table_store_record(thd, table))
 
5537
        DBUG_RETURN(1);
 
5538
    }
 
5539
  }
 
5540
  DBUG_RETURN(0);
 
5541
}
 
5542
 
 
5543
struct schema_table_ref 
 
5544
{
 
5545
  const char *table_name;
 
5546
  ST_SCHEMA_TABLE *schema_table;
 
5547
};
 
5548
 
 
5549
 
 
5550
/*
 
5551
  Find schema_tables elment by name
 
5552
 
 
5553
  SYNOPSIS
 
5554
    find_schema_table_in_plugin()
 
5555
    thd                 thread handler
 
5556
    plugin              plugin
 
5557
    table_name          table name
 
5558
 
 
5559
  RETURN
 
5560
    0   table not found
 
5561
    1   found the schema table
 
5562
*/
 
5563
static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin,
 
5564
                                           void* p_table)
 
5565
{
 
5566
  schema_table_ref *p_schema_table= (schema_table_ref *)p_table;
 
5567
  const char* table_name= p_schema_table->table_name;
 
5568
  ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *);
 
5569
  DBUG_ENTER("find_schema_table_in_plugin");
 
5570
 
 
5571
  if (!my_strcasecmp(system_charset_info,
 
5572
                     schema_table->table_name,
 
5573
                     table_name)) {
 
5574
    p_schema_table->schema_table= schema_table;
 
5575
    DBUG_RETURN(1);
 
5576
  }
 
5577
 
 
5578
  DBUG_RETURN(0);
 
5579
}
 
5580
 
 
5581
 
 
5582
/*
 
5583
  Find schema_tables elment by name
 
5584
 
 
5585
  SYNOPSIS
 
5586
    find_schema_table()
 
5587
    thd                 thread handler
 
5588
    table_name          table name
 
5589
 
 
5590
  RETURN
 
5591
    0   table not found
 
5592
    #   pointer to 'schema_tables' element
 
5593
*/
 
5594
 
 
5595
ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name)
 
5596
{
 
5597
  schema_table_ref schema_table_a;
 
5598
  ST_SCHEMA_TABLE *schema_table= schema_tables;
 
5599
  DBUG_ENTER("find_schema_table");
 
5600
 
 
5601
  for (; schema_table->table_name; schema_table++)
 
5602
  {
 
5603
    if (!my_strcasecmp(system_charset_info,
 
5604
                       schema_table->table_name,
 
5605
                       table_name))
 
5606
      DBUG_RETURN(schema_table);
 
5607
  }
 
5608
 
 
5609
  schema_table_a.table_name= table_name;
 
5610
  if (plugin_foreach(thd, find_schema_table_in_plugin, 
 
5611
                     MYSQL_INFORMATION_SCHEMA_PLUGIN, &schema_table_a))
 
5612
    DBUG_RETURN(schema_table_a.schema_table);
 
5613
 
 
5614
  DBUG_RETURN(NULL);
 
5615
}
 
5616
 
 
5617
 
 
5618
ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx)
 
5619
{
 
5620
  return &schema_tables[schema_table_idx];
 
5621
}
 
5622
 
 
5623
 
 
5624
/**
 
5625
  Create information_schema table using schema_table data.
 
5626
 
 
5627
  @note
 
5628
    For MYSQL_TYPE_DECIMAL fields only, the field_length member has encoded
 
5629
    into it two numbers, based on modulus of base-10 numbers.  In the ones
 
5630
    position is the number of decimals.  Tens position is unused.  In the
 
5631
    hundreds and thousands position is a two-digit decimal number representing
 
5632
    length.  Encode this value with  (decimals*100)+length  , where
 
5633
    0<decimals<10 and 0<=length<100 .
 
5634
 
 
5635
  @param
 
5636
    thd                   thread handler
 
5637
 
 
5638
  @param table_list Used to pass I_S table information(fields info, tables
 
5639
  parameters etc) and table name.
 
5640
 
 
5641
  @retval  \#             Pointer to created table
 
5642
  @retval  NULL           Can't create table
 
5643
*/
 
5644
 
 
5645
TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
 
5646
{
 
5647
  int field_count= 0;
 
5648
  Item *item;
 
5649
  TABLE *table;
 
5650
  List<Item> field_list;
 
5651
  ST_SCHEMA_TABLE *schema_table= table_list->schema_table;
 
5652
  ST_FIELD_INFO *fields_info= schema_table->fields_info;
 
5653
  CHARSET_INFO *cs= system_charset_info;
 
5654
  DBUG_ENTER("create_schema_table");
 
5655
 
 
5656
  for (; fields_info->field_name; fields_info++)
 
5657
  {
 
5658
    switch (fields_info->field_type) {
 
5659
    case MYSQL_TYPE_TINY:
 
5660
    case MYSQL_TYPE_LONG:
 
5661
    case MYSQL_TYPE_SHORT:
 
5662
    case MYSQL_TYPE_LONGLONG:
 
5663
    case MYSQL_TYPE_INT24:
 
5664
      if (!(item= new Item_return_int(fields_info->field_name,
 
5665
                                      fields_info->field_length,
 
5666
                                      fields_info->field_type,
 
5667
                                      fields_info->value)))
 
5668
      {
 
5669
        DBUG_RETURN(0);
 
5670
      }
 
5671
      item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
 
5672
      break;
 
5673
    case MYSQL_TYPE_DATE:
 
5674
    case MYSQL_TYPE_TIME:
 
5675
    case MYSQL_TYPE_TIMESTAMP:
 
5676
    case MYSQL_TYPE_DATETIME:
 
5677
      if (!(item=new Item_return_date_time(fields_info->field_name,
 
5678
                                           fields_info->field_type)))
 
5679
      {
 
5680
        DBUG_RETURN(0);
 
5681
      }
 
5682
      break;
 
5683
    case MYSQL_TYPE_FLOAT:
 
5684
    case MYSQL_TYPE_DOUBLE:
 
5685
      if ((item= new Item_float(fields_info->field_name, 0.0, NOT_FIXED_DEC, 
 
5686
                           fields_info->field_length)) == NULL)
 
5687
        DBUG_RETURN(NULL);
 
5688
      break;
 
5689
    case MYSQL_TYPE_DECIMAL:
 
5690
    case MYSQL_TYPE_NEWDECIMAL:
 
5691
      if (!(item= new Item_decimal((longlong) fields_info->value, false)))
 
5692
      {
 
5693
        DBUG_RETURN(0);
 
5694
      }
 
5695
      item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED);
 
5696
      item->decimals= fields_info->field_length%10;
 
5697
      item->max_length= (fields_info->field_length/100)%100;
 
5698
      if (item->unsigned_flag == 0)
 
5699
        item->max_length+= 1;
 
5700
      if (item->decimals > 0)
 
5701
        item->max_length+= 1;
 
5702
      item->set_name(fields_info->field_name,
 
5703
                     strlen(fields_info->field_name), cs);
 
5704
      break;
 
5705
    case MYSQL_TYPE_TINY_BLOB:
 
5706
    case MYSQL_TYPE_MEDIUM_BLOB:
 
5707
    case MYSQL_TYPE_LONG_BLOB:
 
5708
    case MYSQL_TYPE_BLOB:
 
5709
      if (!(item= new Item_blob(fields_info->field_name,
 
5710
                                fields_info->field_length)))
 
5711
      {
 
5712
        DBUG_RETURN(0);
 
5713
      }
 
5714
      break;
 
5715
    default:
 
5716
      /* Don't let unimplemented types pass through. Could be a grave error. */
 
5717
      DBUG_ASSERT(fields_info->field_type == MYSQL_TYPE_STRING);
 
5718
 
 
5719
      if (!(item= new Item_empty_string("", fields_info->field_length, cs)))
 
5720
      {
 
5721
        DBUG_RETURN(0);
 
5722
      }
 
5723
      item->set_name(fields_info->field_name,
 
5724
                     strlen(fields_info->field_name), cs);
 
5725
      break;
 
5726
    }
 
5727
    field_list.push_back(item);
 
5728
    item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL);
 
5729
    field_count++;
 
5730
  }
 
5731
  TMP_TABLE_PARAM *tmp_table_param =
 
5732
    (TMP_TABLE_PARAM*) (thd->alloc(sizeof(TMP_TABLE_PARAM)));
 
5733
  tmp_table_param->init();
 
5734
  tmp_table_param->table_charset= cs;
 
5735
  tmp_table_param->field_count= field_count;
 
5736
  tmp_table_param->schema_table= 1;
 
5737
  SELECT_LEX *select_lex= thd->lex->current_select;
 
5738
  if (!(table= create_tmp_table(thd, tmp_table_param,
 
5739
                                field_list, (ORDER*) 0, 0, 0, 
 
5740
                                (select_lex->options | thd->options |
 
5741
                                 TMP_TABLE_ALL_COLUMNS),
 
5742
                                HA_POS_ERROR, table_list->alias)))
 
5743
    DBUG_RETURN(0);
 
5744
  my_bitmap_map* bitmaps=
 
5745
    (my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count));
 
5746
  bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
 
5747
              FALSE);
 
5748
  table->read_set= &table->def_read_set;
 
5749
  bitmap_clear_all(table->read_set);
 
5750
  table_list->schema_table_param= tmp_table_param;
 
5751
  DBUG_RETURN(table);
 
5752
}
 
5753
 
 
5754
 
 
5755
/*
 
5756
  For old SHOW compatibility. It is used when
 
5757
  old SHOW doesn't have generated column names
 
5758
  Make list of fields for SHOW
 
5759
 
 
5760
  SYNOPSIS
 
5761
    make_old_format()
 
5762
    thd                 thread handler
 
5763
    schema_table        pointer to 'schema_tables' element
 
5764
 
 
5765
  RETURN
 
5766
   1    error
 
5767
   0    success
 
5768
*/
 
5769
 
 
5770
int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
5771
{
 
5772
  ST_FIELD_INFO *field_info= schema_table->fields_info;
 
5773
  Name_resolution_context *context= &thd->lex->select_lex.context;
 
5774
  for (; field_info->field_name; field_info++)
 
5775
  {
 
5776
    if (field_info->old_name)
 
5777
    {
 
5778
      Item_field *field= new Item_field(context,
 
5779
                                        NullS, NullS, field_info->field_name);
 
5780
      if (field)
 
5781
      {
 
5782
        field->set_name(field_info->old_name,
 
5783
                        strlen(field_info->old_name),
 
5784
                        system_charset_info);
 
5785
        if (add_item_to_list(thd, field))
 
5786
          return 1;
 
5787
      }
 
5788
    }
 
5789
  }
 
5790
  return 0;
 
5791
}
 
5792
 
 
5793
 
 
5794
int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
5795
{
 
5796
  char tmp[128];
 
5797
  LEX *lex= thd->lex;
 
5798
  SELECT_LEX *sel= lex->current_select;
 
5799
  Name_resolution_context *context= &sel->context;
 
5800
 
 
5801
  if (!sel->item_list.elements)
 
5802
  {
 
5803
    ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
 
5804
    String buffer(tmp,sizeof(tmp), system_charset_info);
 
5805
    Item_field *field= new Item_field(context,
 
5806
                                      NullS, NullS, field_info->field_name);
 
5807
    if (!field || add_item_to_list(thd, field))
 
5808
      return 1;
 
5809
    buffer.length(0);
 
5810
    buffer.append(field_info->old_name);
 
5811
    if (lex->wild && lex->wild->ptr())
 
5812
    {
 
5813
      buffer.append(STRING_WITH_LEN(" ("));
 
5814
      buffer.append(lex->wild->ptr());
 
5815
      buffer.append(')');
 
5816
    }
 
5817
    field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
 
5818
  }
 
5819
  return 0;
 
5820
}
 
5821
 
 
5822
 
 
5823
int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
5824
{
 
5825
  char tmp[128];
 
5826
  String buffer(tmp,sizeof(tmp), thd->charset());
 
5827
  LEX *lex= thd->lex;
 
5828
  Name_resolution_context *context= &lex->select_lex.context;
 
5829
 
 
5830
  ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
 
5831
  buffer.length(0);
 
5832
  buffer.append(field_info->old_name);
 
5833
  buffer.append(lex->select_lex.db);
 
5834
  if (lex->wild && lex->wild->ptr())
 
5835
  {
 
5836
    buffer.append(STRING_WITH_LEN(" ("));
 
5837
    buffer.append(lex->wild->ptr());
 
5838
    buffer.append(')');
 
5839
  }
 
5840
  Item_field *field= new Item_field(context,
 
5841
                                    NullS, NullS, field_info->field_name);
 
5842
  if (add_item_to_list(thd, field))
 
5843
    return 1;
 
5844
  field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
 
5845
  if (thd->lex->verbose)
 
5846
  {
 
5847
    field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
 
5848
    field_info= &schema_table->fields_info[3];
 
5849
    field= new Item_field(context, NullS, NullS, field_info->field_name);
 
5850
    if (add_item_to_list(thd, field))
 
5851
      return 1;
 
5852
    field->set_name(field_info->old_name, strlen(field_info->old_name),
 
5853
                    system_charset_info);
 
5854
  }
 
5855
  return 0;
 
5856
}
 
5857
 
 
5858
 
 
5859
int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
5860
{
 
5861
  int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
 
5862
  int *field_num= fields_arr;
 
5863
  ST_FIELD_INFO *field_info;
 
5864
  Name_resolution_context *context= &thd->lex->select_lex.context;
 
5865
 
 
5866
  for (; *field_num >= 0; field_num++)
 
5867
  {
 
5868
    field_info= &schema_table->fields_info[*field_num];
 
5869
    if (!thd->lex->verbose && (*field_num == 13 ||
 
5870
                               *field_num == 17 ||
 
5871
                               *field_num == 18))
 
5872
      continue;
 
5873
    Item_field *field= new Item_field(context,
 
5874
                                      NullS, NullS, field_info->field_name);
 
5875
    if (field)
 
5876
    {
 
5877
      field->set_name(field_info->old_name,
 
5878
                      strlen(field_info->old_name),
 
5879
                      system_charset_info);
 
5880
      if (add_item_to_list(thd, field))
 
5881
        return 1;
 
5882
    }
 
5883
  }
 
5884
  return 0;
 
5885
}
 
5886
 
 
5887
 
 
5888
int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
5889
{
 
5890
  int fields_arr[]= {0, 2, 1, 3, -1};
 
5891
  int *field_num= fields_arr;
 
5892
  ST_FIELD_INFO *field_info;
 
5893
  Name_resolution_context *context= &thd->lex->select_lex.context;
 
5894
 
 
5895
  for (; *field_num >= 0; field_num++)
 
5896
  {
 
5897
    field_info= &schema_table->fields_info[*field_num];
 
5898
    Item_field *field= new Item_field(context,
 
5899
                                      NullS, NullS, field_info->field_name);
 
5900
    if (field)
 
5901
    {
 
5902
      field->set_name(field_info->old_name,
 
5903
                      strlen(field_info->old_name),
 
5904
                      system_charset_info);
 
5905
      if (add_item_to_list(thd, field))
 
5906
        return 1;
 
5907
    }
 
5908
  }
 
5909
  return 0;
 
5910
}
 
5911
 
 
5912
 
 
5913
int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
 
5914
{
 
5915
  int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, 20, 21, 22, -1};
 
5916
  int *field_num= fields_arr;
 
5917
  ST_FIELD_INFO *field_info;
 
5918
  Name_resolution_context *context= &thd->lex->select_lex.context;
 
5919
 
 
5920
  for (; *field_num >= 0; field_num++)
 
5921
  {
 
5922
    field_info= &schema_table->fields_info[*field_num];
 
5923
    Item_field *field= new Item_field(context,
 
5924
                                      NullS, NullS, field_info->field_name);
 
5925
    if (field)
 
5926
    {
 
5927
      field->set_name(field_info->old_name,
 
5928
                      strlen(field_info->old_name),
 
5929
                      system_charset_info);
 
5930
      if (add_item_to_list(thd, field))
 
5931
        return 1;
 
5932
    }
 
5933
  }
 
5934
  return 0;
 
5935
}
 
5936
 
 
5937
 
 
5938
/*
 
5939
  Create information_schema table
 
5940
 
 
5941
  SYNOPSIS
 
5942
  mysql_schema_table()
 
5943
    thd                thread handler
 
5944
    lex                pointer to LEX
 
5945
    table_list         pointer to table_list
 
5946
 
 
5947
  RETURN
 
5948
    0   success
 
5949
    1   error
 
5950
*/
 
5951
 
 
5952
int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
 
5953
{
 
5954
  TABLE *table;
 
5955
  DBUG_ENTER("mysql_schema_table");
 
5956
  if (!(table= table_list->schema_table->create_table(thd, table_list)))
 
5957
    DBUG_RETURN(1);
 
5958
  table->s->tmp_table= SYSTEM_TMP_TABLE;
 
5959
  table->grant.privilege= SELECT_ACL;
 
5960
  /*
 
5961
    This test is necessary to make
 
5962
    case insensitive file systems +
 
5963
    upper case table names(information schema tables) +
 
5964
    views
 
5965
    working correctly
 
5966
  */
 
5967
  if (table_list->schema_table_name)
 
5968
    table->alias_name_used= my_strcasecmp(table_alias_charset,
 
5969
                                          table_list->schema_table_name,
 
5970
                                          table_list->alias);
 
5971
  table_list->table_name= table->s->table_name.str;
 
5972
  table_list->table_name_length= table->s->table_name.length;
 
5973
  table_list->table= table;
 
5974
  table->next= thd->derived_tables;
 
5975
  thd->derived_tables= table;
 
5976
  table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
 
5977
  lex->safe_to_cache_query= 0;
 
5978
 
 
5979
  if (table_list->schema_table_reformed) // show command
 
5980
  {
 
5981
    SELECT_LEX *sel= lex->current_select;
 
5982
    Item *item;
 
5983
    Field_translator *transl, *org_transl;
 
5984
 
 
5985
    if (table_list->field_translation)
 
5986
    {
 
5987
      Field_translator *end= table_list->field_translation_end;
 
5988
      for (transl= table_list->field_translation; transl < end; transl++)
 
5989
      {
 
5990
        if (!transl->item->fixed &&
 
5991
            transl->item->fix_fields(thd, &transl->item))
 
5992
          DBUG_RETURN(1);
 
5993
      }
 
5994
      DBUG_RETURN(0);
 
5995
    }
 
5996
    List_iterator_fast<Item> it(sel->item_list);
 
5997
    if (!(transl=
 
5998
          (Field_translator*)(thd->stmt_arena->
 
5999
                              alloc(sel->item_list.elements *
 
6000
                                    sizeof(Field_translator)))))
 
6001
    {
 
6002
      DBUG_RETURN(1);
 
6003
    }
 
6004
    for (org_transl= transl; (item= it++); transl++)
 
6005
    {
 
6006
      transl->item= item;
 
6007
      transl->name= item->name;
 
6008
      if (!item->fixed && item->fix_fields(thd, &transl->item))
 
6009
      {
 
6010
        DBUG_RETURN(1);
 
6011
      }
 
6012
    }
 
6013
    table_list->field_translation= org_transl;
 
6014
    table_list->field_translation_end= transl;
 
6015
  }
 
6016
 
 
6017
  DBUG_RETURN(0);
 
6018
}
 
6019
 
 
6020
 
 
6021
/*
 
6022
  Generate select from information_schema table
 
6023
 
 
6024
  SYNOPSIS
 
6025
    make_schema_select()
 
6026
    thd                  thread handler
 
6027
    sel                  pointer to SELECT_LEX
 
6028
    schema_table_idx     index of 'schema_tables' element
 
6029
 
 
6030
  RETURN
 
6031
    0   success
 
6032
    1   error
 
6033
*/
 
6034
 
 
6035
int make_schema_select(THD *thd, SELECT_LEX *sel,
 
6036
                       enum enum_schema_tables schema_table_idx)
 
6037
{
 
6038
  ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
 
6039
  LEX_STRING db, table;
 
6040
  DBUG_ENTER("make_schema_select");
 
6041
  DBUG_PRINT("enter", ("mysql_schema_select: %s", schema_table->table_name));
 
6042
  /*
 
6043
     We have to make non const db_name & table_name
 
6044
     because of lower_case_table_names
 
6045
  */
 
6046
  thd->make_lex_string(&db, INFORMATION_SCHEMA_NAME.str,
 
6047
                       INFORMATION_SCHEMA_NAME.length, 0);
 
6048
  thd->make_lex_string(&table, schema_table->table_name,
 
6049
                       strlen(schema_table->table_name), 0);
 
6050
  if (schema_table->old_format(thd, schema_table) ||   /* Handle old syntax */
 
6051
      !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
 
6052
                              0, 0, TL_READ))
 
6053
  {
 
6054
    DBUG_RETURN(1);
 
6055
  }
 
6056
  DBUG_RETURN(0);
 
6057
}
 
6058
 
 
6059
 
 
6060
/*
 
6061
  Fill temporary schema tables before SELECT
 
6062
 
 
6063
  SYNOPSIS
 
6064
    get_schema_tables_result()
 
6065
    join  join which use schema tables
 
6066
    executed_place place where I_S table processed
 
6067
 
 
6068
  RETURN
 
6069
    FALSE success
 
6070
    TRUE  error
 
6071
*/
 
6072
 
 
6073
bool get_schema_tables_result(JOIN *join,
 
6074
                              enum enum_schema_table_state executed_place)
 
6075
{
 
6076
  JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
 
6077
  THD *thd= join->thd;
 
6078
  LEX *lex= thd->lex;
 
6079
  bool result= 0;
 
6080
  DBUG_ENTER("get_schema_tables_result");
 
6081
 
 
6082
  thd->no_warnings_for_error= 1;
 
6083
  for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++)
 
6084
  {  
 
6085
    if (!tab->table || !tab->table->pos_in_table_list)
 
6086
      break;
 
6087
 
 
6088
    TABLE_LIST *table_list= tab->table->pos_in_table_list;
 
6089
    if (table_list->schema_table && thd->fill_information_schema_tables())
 
6090
    {
 
6091
      bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
 
6092
                          lex->current_select->master_unit()->item);
 
6093
 
 
6094
      /* A value of 0 indicates a dummy implementation */
 
6095
      if (table_list->schema_table->fill_table == 0)
 
6096
        continue;
 
6097
 
 
6098
      /* skip I_S optimizations specific to get_all_tables */
 
6099
      if (thd->lex->describe &&
 
6100
          (table_list->schema_table->fill_table != get_all_tables))
 
6101
        continue;
 
6102
 
 
6103
      /*
 
6104
        If schema table is already processed and
 
6105
        the statement is not a subselect then
 
6106
        we don't need to fill this table again.
 
6107
        If schema table is already processed and
 
6108
        schema_table_state != executed_place then
 
6109
        table is already processed and
 
6110
        we should skip second data processing.
 
6111
      */
 
6112
      if (table_list->schema_table_state &&
 
6113
          (!is_subselect || table_list->schema_table_state != executed_place))
 
6114
        continue;
 
6115
 
 
6116
      /*
 
6117
        if table is used in a subselect and
 
6118
        table has been processed earlier with the same
 
6119
        'executed_place' value then we should refresh the table.
 
6120
      */
 
6121
      if (table_list->schema_table_state && is_subselect)
 
6122
      {
 
6123
        table_list->table->file->extra(HA_EXTRA_NO_CACHE);
 
6124
        table_list->table->file->extra(HA_EXTRA_RESET_STATE);
 
6125
        table_list->table->file->ha_delete_all_rows();
 
6126
        free_io_cache(table_list->table);
 
6127
        filesort_free_buffers(table_list->table,1);
 
6128
        table_list->table->null_row= 0;
 
6129
      }
 
6130
      else
 
6131
        table_list->table->file->stats.records= 0;
 
6132
 
 
6133
      if (table_list->schema_table->fill_table(thd, table_list,
 
6134
                                               tab->select_cond))
 
6135
      {
 
6136
        result= 1;
 
6137
        join->error= 1;
 
6138
        tab->read_record.file= table_list->table->file;
 
6139
        table_list->schema_table_state= executed_place;
 
6140
        break;
 
6141
      }
 
6142
      tab->read_record.file= table_list->table->file;
 
6143
      table_list->schema_table_state= executed_place;
 
6144
    }
 
6145
  }
 
6146
  thd->no_warnings_for_error= 0;
 
6147
  DBUG_RETURN(result);
 
6148
}
 
6149
 
 
6150
struct run_hton_fill_schema_files_args
 
6151
{
 
6152
  TABLE_LIST *tables;
 
6153
  COND *cond;
 
6154
};
 
6155
 
 
6156
static my_bool run_hton_fill_schema_files(THD *thd, plugin_ref plugin,
 
6157
                                          void *arg)
 
6158
{
 
6159
  struct run_hton_fill_schema_files_args *args=
 
6160
    (run_hton_fill_schema_files_args *) arg;
 
6161
  handlerton *hton= plugin_data(plugin, handlerton *);
 
6162
  if(hton->fill_files_table && hton->state == SHOW_OPTION_YES)
 
6163
    hton->fill_files_table(hton, thd, args->tables, args->cond);
 
6164
  return false;
 
6165
}
 
6166
 
 
6167
int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond)
 
6168
{
 
6169
  DBUG_ENTER("fill_schema_files");
 
6170
 
 
6171
  struct run_hton_fill_schema_files_args args;
 
6172
  args.tables= tables;
 
6173
  args.cond= cond;
 
6174
 
 
6175
  plugin_foreach(thd, run_hton_fill_schema_files,
 
6176
                 MYSQL_STORAGE_ENGINE_PLUGIN, &args);
 
6177
 
 
6178
  DBUG_RETURN(0);
 
6179
}
 
6180
 
 
6181
 
 
6182
ST_FIELD_INFO schema_fields_info[]=
 
6183
{
 
6184
  {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6185
  {"SCHEMA_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
 
6186
   SKIP_OPEN_TABLE},
 
6187
  {"DEFAULT_CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
 
6188
   SKIP_OPEN_TABLE},
 
6189
  {"DEFAULT_COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
 
6190
   SKIP_OPEN_TABLE},
 
6191
  {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6192
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6193
};
 
6194
 
 
6195
 
 
6196
ST_FIELD_INFO tables_fields_info[]=
 
6197
{
 
6198
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6199
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6200
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
 
6201
   SKIP_OPEN_TABLE},
 
6202
  {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
6203
  {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine", OPEN_FRM_ONLY},
 
6204
  {"VERSION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
6205
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Version", OPEN_FRM_ONLY},
 
6206
  {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", OPEN_FULL_TABLE},
 
6207
  {"TABLE_ROWS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
6208
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", OPEN_FULL_TABLE},
 
6209
  {"AVG_ROW_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 
 
6210
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", OPEN_FULL_TABLE},
 
6211
  {"DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 
 
6212
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", OPEN_FULL_TABLE},
 
6213
  {"MAX_DATA_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
6214
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", OPEN_FULL_TABLE},
 
6215
  {"INDEX_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 
 
6216
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", OPEN_FULL_TABLE},
 
6217
  {"DATA_FREE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
6218
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", OPEN_FULL_TABLE},
 
6219
  {"AUTO_INCREMENT", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG, 0, 
 
6220
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Auto_increment", OPEN_FULL_TABLE},
 
6221
  {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", OPEN_FULL_TABLE},
 
6222
  {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", OPEN_FULL_TABLE},
 
6223
  {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Check_time", OPEN_FULL_TABLE},
 
6224
  {"TABLE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 1, "Collation",
 
6225
   OPEN_FRM_ONLY},
 
6226
  {"CHECKSUM", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
6227
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", OPEN_FULL_TABLE},
 
6228
  {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options",
 
6229
   OPEN_FRM_ONLY},
 
6230
  {"TABLE_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY},
 
6231
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6232
};
 
6233
 
 
6234
 
 
6235
ST_FIELD_INFO columns_fields_info[]=
 
6236
{
 
6237
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
 
6238
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
6239
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
6240
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Field",
 
6241
   OPEN_FRM_ONLY},
 
6242
  {"ORDINAL_POSITION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
 
6243
   MY_I_S_UNSIGNED, 0, OPEN_FRM_ONLY},
 
6244
  {"COLUMN_DEFAULT", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0,
 
6245
   1, "Default", OPEN_FRM_ONLY},
 
6246
  {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
 
6247
  {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
6248
  {"CHARACTER_MAXIMUM_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
 
6249
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
 
6250
  {"CHARACTER_OCTET_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
 
6251
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
 
6252
  {"NUMERIC_PRECISION", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG,
 
6253
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
 
6254
  {"NUMERIC_SCALE", MY_INT64_NUM_DECIMAL_DIGITS , MYSQL_TYPE_LONGLONG,
 
6255
   0, (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FRM_ONLY},
 
6256
  {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 1, 0,
 
6257
   OPEN_FRM_ONLY},
 
6258
  {"COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 1, "Collation",
 
6259
   OPEN_FRM_ONLY},
 
6260
  {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type", OPEN_FRM_ONLY},
 
6261
  {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key", OPEN_FRM_ONLY},
 
6262
  {"EXTRA", 27, MYSQL_TYPE_STRING, 0, 0, "Extra", OPEN_FRM_ONLY},
 
6263
  {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges", OPEN_FRM_ONLY},
 
6264
  {"COLUMN_COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY},
 
6265
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6266
};
 
6267
 
 
6268
 
 
6269
ST_FIELD_INFO charsets_fields_info[]=
 
6270
{
 
6271
  {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, "Charset",
 
6272
   SKIP_OPEN_TABLE},
 
6273
  {"DEFAULT_COLLATE_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6274
   "Default collation", SKIP_OPEN_TABLE},
 
6275
  {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description",
 
6276
   SKIP_OPEN_TABLE},
 
6277
  {"MAXLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Maxlen", SKIP_OPEN_TABLE},
 
6278
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6279
};
 
6280
 
 
6281
 
 
6282
ST_FIELD_INFO collation_fields_info[]=
 
6283
{
 
6284
  {"COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, "Collation",
 
6285
   SKIP_OPEN_TABLE},
 
6286
  {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, "Charset",
 
6287
   SKIP_OPEN_TABLE},
 
6288
  {"ID", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Id",
 
6289
   SKIP_OPEN_TABLE},
 
6290
  {"IS_DEFAULT", 3, MYSQL_TYPE_STRING, 0, 0, "Default", SKIP_OPEN_TABLE},
 
6291
  {"IS_COMPILED", 3, MYSQL_TYPE_STRING, 0, 0, "Compiled", SKIP_OPEN_TABLE},
 
6292
  {"SORTLEN", 3, MYSQL_TYPE_LONGLONG, 0, 0, "Sortlen", SKIP_OPEN_TABLE},
 
6293
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6294
};
 
6295
 
 
6296
 
 
6297
ST_FIELD_INFO engines_fields_info[]=
 
6298
{
 
6299
  {"ENGINE", 64, MYSQL_TYPE_STRING, 0, 0, "Engine", SKIP_OPEN_TABLE},
 
6300
  {"SUPPORT", 8, MYSQL_TYPE_STRING, 0, 0, "Support", SKIP_OPEN_TABLE},
 
6301
  {"COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment", SKIP_OPEN_TABLE},
 
6302
  {"TRANSACTIONS", 3, MYSQL_TYPE_STRING, 0, 1, "Transactions", SKIP_OPEN_TABLE},
 
6303
  {"XA", 3, MYSQL_TYPE_STRING, 0, 1, "XA", SKIP_OPEN_TABLE},
 
6304
  {"SAVEPOINTS", 3 ,MYSQL_TYPE_STRING, 0, 1, "Savepoints", SKIP_OPEN_TABLE},
 
6305
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6306
};
 
6307
 
 
6308
 
 
6309
ST_FIELD_INFO events_fields_info[]=
 
6310
{
 
6311
  {"EVENT_CATALOG", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6312
  {"EVENT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Db",
 
6313
   SKIP_OPEN_TABLE},
 
6314
  {"EVENT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
 
6315
   SKIP_OPEN_TABLE},
 
6316
  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN_TABLE},
 
6317
  {"TIME_ZONE", 64, MYSQL_TYPE_STRING, 0, 0, "Time zone", SKIP_OPEN_TABLE},
 
6318
  {"EVENT_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6319
  {"EVENT_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6320
  {"EVENT_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
 
6321
  {"EXECUTE_AT", 0, MYSQL_TYPE_DATETIME, 0, 1, "Execute at", SKIP_OPEN_TABLE},
 
6322
  {"INTERVAL_VALUE", 256, MYSQL_TYPE_STRING, 0, 1, "Interval value",
 
6323
   SKIP_OPEN_TABLE},
 
6324
  {"INTERVAL_FIELD", 18, MYSQL_TYPE_STRING, 0, 1, "Interval field",
 
6325
   SKIP_OPEN_TABLE},
 
6326
  {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6327
  {"STARTS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Starts", SKIP_OPEN_TABLE},
 
6328
  {"ENDS", 0, MYSQL_TYPE_DATETIME, 0, 1, "Ends", SKIP_OPEN_TABLE},
 
6329
  {"STATUS", 18, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
 
6330
  {"ON_COMPLETION", 12, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6331
  {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
 
6332
  {"LAST_ALTERED", 0, MYSQL_TYPE_DATETIME, 0, 0, 0, SKIP_OPEN_TABLE},
 
6333
  {"LAST_EXECUTED", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
 
6334
  {"EVENT_COMMENT", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6335
  {"ORIGINATOR", 10, MYSQL_TYPE_LONGLONG, 0, 0, "Originator", SKIP_OPEN_TABLE},
 
6336
  {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6337
   "character_set_client", SKIP_OPEN_TABLE},
 
6338
  {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6339
   "collation_connection", SKIP_OPEN_TABLE},
 
6340
  {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6341
   "Database Collation", SKIP_OPEN_TABLE},
 
6342
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6343
};
 
6344
 
 
6345
 
 
6346
 
 
6347
ST_FIELD_INFO coll_charset_app_fields_info[]=
 
6348
{
 
6349
  {"COLLATION_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
 
6350
   SKIP_OPEN_TABLE},
 
6351
  {"CHARACTER_SET_NAME", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
 
6352
   SKIP_OPEN_TABLE},
 
6353
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6354
};
 
6355
 
 
6356
 
 
6357
ST_FIELD_INFO proc_fields_info[]=
 
6358
{
 
6359
  {"SPECIFIC_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6360
  {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6361
  {"ROUTINE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Db",
 
6362
   SKIP_OPEN_TABLE},
 
6363
  {"ROUTINE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
 
6364
   SKIP_OPEN_TABLE},
 
6365
  {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
 
6366
  {"DTD_IDENTIFIER", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6367
  {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6368
  {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6369
  {"EXTERNAL_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6370
  {"EXTERNAL_LANGUAGE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6371
   SKIP_OPEN_TABLE},
 
6372
  {"PARAMETER_STYLE", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6373
  {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6374
  {"SQL_DATA_ACCESS", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6375
   SKIP_OPEN_TABLE},
 
6376
  {"SQL_PATH", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6377
  {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type",
 
6378
   SKIP_OPEN_TABLE},
 
6379
  {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 0, "Created", SKIP_OPEN_TABLE},
 
6380
  {"LAST_ALTERED", 0, MYSQL_TYPE_DATETIME, 0, 0, "Modified", SKIP_OPEN_TABLE},
 
6381
  {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6382
  {"ROUTINE_COMMENT", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment",
 
6383
   SKIP_OPEN_TABLE},
 
6384
  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", SKIP_OPEN_TABLE},
 
6385
  {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6386
   "character_set_client", SKIP_OPEN_TABLE},
 
6387
  {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6388
   "collation_connection", SKIP_OPEN_TABLE},
 
6389
  {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6390
   "Database Collation", SKIP_OPEN_TABLE},
 
6391
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6392
};
 
6393
 
 
6394
 
 
6395
ST_FIELD_INFO stat_fields_info[]=
 
6396
{
 
6397
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
 
6398
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
6399
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", OPEN_FRM_ONLY},
 
6400
  {"NON_UNIQUE", 1, MYSQL_TYPE_LONGLONG, 0, 0, "Non_unique", OPEN_FRM_ONLY},
 
6401
  {"INDEX_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
6402
  {"INDEX_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name",
 
6403
   OPEN_FRM_ONLY},
 
6404
  {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONGLONG, 0, 0, "Seq_in_index", OPEN_FRM_ONLY},
 
6405
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name",
 
6406
   OPEN_FRM_ONLY},
 
6407
  {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation", OPEN_FRM_ONLY},
 
6408
  {"CARDINALITY", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 1,
 
6409
   "Cardinality", OPEN_FULL_TABLE},
 
6410
  {"SUB_PART", 3, MYSQL_TYPE_LONGLONG, 0, 1, "Sub_part", OPEN_FRM_ONLY},
 
6411
  {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed", OPEN_FRM_ONLY},
 
6412
  {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null", OPEN_FRM_ONLY},
 
6413
  {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type", OPEN_FULL_TABLE},
 
6414
  {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment", OPEN_FRM_ONLY},
 
6415
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6416
};
 
6417
 
 
6418
 
 
6419
ST_FIELD_INFO view_fields_info[]=
 
6420
{
 
6421
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY},
 
6422
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
6423
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY},
 
6424
  {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6425
  {"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6426
  {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6427
  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6428
  {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6429
  {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
 
6430
   OPEN_FULL_TABLE},
 
6431
  {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0,
 
6432
   OPEN_FULL_TABLE},
 
6433
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6434
};
 
6435
 
 
6436
 
 
6437
ST_FIELD_INFO user_privileges_fields_info[]=
 
6438
{
 
6439
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6440
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6441
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6442
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6443
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6444
};
 
6445
 
 
6446
 
 
6447
ST_FIELD_INFO schema_privileges_fields_info[]=
 
6448
{
 
6449
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6450
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6451
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6452
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6453
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6454
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6455
};
 
6456
 
 
6457
 
 
6458
ST_FIELD_INFO table_privileges_fields_info[]=
 
6459
{
 
6460
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6461
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6462
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6463
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6464
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6465
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6466
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6467
};
 
6468
 
 
6469
 
 
6470
ST_FIELD_INFO column_privileges_fields_info[]=
 
6471
{
 
6472
  {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6473
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6474
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6475
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6476
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6477
  {"PRIVILEGE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6478
  {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6479
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6480
};
 
6481
 
 
6482
 
 
6483
ST_FIELD_INFO table_constraints_fields_info[]=
 
6484
{
 
6485
  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6486
  {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6487
   OPEN_FULL_TABLE},
 
6488
  {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6489
   OPEN_FULL_TABLE},
 
6490
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6491
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6492
  {"CONSTRAINT_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6493
   OPEN_FULL_TABLE},
 
6494
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6495
};
 
6496
 
 
6497
 
 
6498
ST_FIELD_INFO key_column_usage_fields_info[]=
 
6499
{
 
6500
  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6501
  {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6502
   OPEN_FULL_TABLE},
 
6503
  {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6504
   OPEN_FULL_TABLE},
 
6505
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6506
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6507
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6508
  {"COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6509
  {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FULL_TABLE},
 
6510
  {"POSITION_IN_UNIQUE_CONSTRAINT", 10 ,MYSQL_TYPE_LONGLONG, 0, 1, 0,
 
6511
   OPEN_FULL_TABLE},
 
6512
  {"REFERENCED_TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6513
   OPEN_FULL_TABLE},
 
6514
  {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6515
   OPEN_FULL_TABLE},
 
6516
  {"REFERENCED_COLUMN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6517
   OPEN_FULL_TABLE},
 
6518
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6519
};
 
6520
 
 
6521
 
 
6522
ST_FIELD_INFO table_names_fields_info[]=
 
6523
{
 
6524
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6525
  {"TABLE_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6526
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_",
 
6527
   SKIP_OPEN_TABLE},
 
6528
  {"TABLE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type",
 
6529
   OPEN_FRM_ONLY},
 
6530
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6531
};
 
6532
 
 
6533
 
 
6534
ST_FIELD_INFO open_tables_fields_info[]=
 
6535
{
 
6536
  {"Database", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Database",
 
6537
   SKIP_OPEN_TABLE},
 
6538
  {"Table",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", SKIP_OPEN_TABLE},
 
6539
  {"In_use", 1, MYSQL_TYPE_LONGLONG, 0, 0, "In_use", SKIP_OPEN_TABLE},
 
6540
  {"Name_locked", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Name_locked", SKIP_OPEN_TABLE},
 
6541
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6542
};
 
6543
 
 
6544
 
 
6545
ST_FIELD_INFO triggers_fields_info[]=
 
6546
{
 
6547
  {"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6548
  {"TRIGGER_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6549
  {"TRIGGER_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Trigger",
 
6550
   OPEN_FULL_TABLE},
 
6551
  {"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event", OPEN_FULL_TABLE},
 
6552
  {"EVENT_OBJECT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6553
   OPEN_FULL_TABLE},
 
6554
  {"EVENT_OBJECT_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6555
   OPEN_FULL_TABLE},
 
6556
  {"EVENT_OBJECT_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table",
 
6557
   OPEN_FULL_TABLE},
 
6558
  {"ACTION_ORDER", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FULL_TABLE},
 
6559
  {"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6560
  {"ACTION_STATEMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Statement",
 
6561
   OPEN_FULL_TABLE},
 
6562
  {"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6563
  {"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing", OPEN_FULL_TABLE},
 
6564
  {"ACTION_REFERENCE_OLD_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6565
   OPEN_FULL_TABLE},
 
6566
  {"ACTION_REFERENCE_NEW_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6567
   OPEN_FULL_TABLE},
 
6568
  {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6569
  {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6570
  {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 1, "Created", OPEN_FULL_TABLE},
 
6571
  {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, "sql_mode", OPEN_FULL_TABLE},
 
6572
  {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", OPEN_FULL_TABLE},
 
6573
  {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6574
   "character_set_client", OPEN_FULL_TABLE},
 
6575
  {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6576
   "collation_connection", OPEN_FULL_TABLE},
 
6577
  {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0,
 
6578
   "Database Collation", OPEN_FULL_TABLE},
 
6579
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6580
};
 
6581
 
 
6582
 
 
6583
ST_FIELD_INFO partitions_fields_info[]=
 
6584
{
 
6585
  {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6586
  {"TABLE_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6587
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6588
  {"PARTITION_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6589
  {"SUBPARTITION_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6590
   OPEN_FULL_TABLE},
 
6591
  {"PARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONGLONG, 0,
 
6592
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
 
6593
  {"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONGLONG, 0,
 
6594
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
 
6595
  {"PARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6596
  {"SUBPARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6597
  {"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6598
  {"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0,
 
6599
   OPEN_FULL_TABLE},
 
6600
  {"PARTITION_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6601
  {"TABLE_ROWS", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
 
6602
   OPEN_FULL_TABLE},
 
6603
  {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
 
6604
   OPEN_FULL_TABLE},
 
6605
  {"DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
 
6606
   OPEN_FULL_TABLE},
 
6607
  {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0,
 
6608
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
 
6609
  {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
 
6610
   OPEN_FULL_TABLE},
 
6611
  {"DATA_FREE", 21 , MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, 0,
 
6612
   OPEN_FULL_TABLE},
 
6613
  {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, OPEN_FULL_TABLE},
 
6614
  {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, OPEN_FULL_TABLE},
 
6615
  {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, OPEN_FULL_TABLE},
 
6616
  {"CHECKSUM", 21 , MYSQL_TYPE_LONGLONG, 0,
 
6617
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
 
6618
  {"PARTITION_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6619
  {"NODEGROUP", 12 , MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6620
  {"TABLESPACE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6621
   OPEN_FULL_TABLE},
 
6622
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6623
};
 
6624
 
 
6625
 
 
6626
ST_FIELD_INFO variables_fields_info[]=
 
6627
{
 
6628
  {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name",
 
6629
   SKIP_OPEN_TABLE},
 
6630
  {"VARIABLE_VALUE", 1024, MYSQL_TYPE_STRING, 0, 1, "Value", SKIP_OPEN_TABLE},
 
6631
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6632
};
 
6633
 
 
6634
 
 
6635
ST_FIELD_INFO processlist_fields_info[]=
 
6636
{
 
6637
  {"ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Id", SKIP_OPEN_TABLE},
 
6638
  {"USER", 16, MYSQL_TYPE_STRING, 0, 0, "User", SKIP_OPEN_TABLE},
 
6639
  {"HOST", LIST_PROCESS_HOST_LEN,  MYSQL_TYPE_STRING, 0, 0, "Host",
 
6640
   SKIP_OPEN_TABLE},
 
6641
  {"DB", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Db", SKIP_OPEN_TABLE},
 
6642
  {"COMMAND", 16, MYSQL_TYPE_STRING, 0, 0, "Command", SKIP_OPEN_TABLE},
 
6643
  {"TIME", 7, MYSQL_TYPE_LONG, 0, 0, "Time", SKIP_OPEN_TABLE},
 
6644
  {"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE},
 
6645
  {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
 
6646
   SKIP_OPEN_TABLE},
 
6647
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6648
};
 
6649
 
 
6650
 
 
6651
ST_FIELD_INFO plugin_fields_info[]=
 
6652
{
 
6653
  {"PLUGIN_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name",
 
6654
   SKIP_OPEN_TABLE},
 
6655
  {"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6656
  {"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status", SKIP_OPEN_TABLE},
 
6657
  {"PLUGIN_TYPE", 80, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE},
 
6658
  {"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6659
  {"PLUGIN_LIBRARY", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, "Library",
 
6660
   SKIP_OPEN_TABLE},
 
6661
  {"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6662
  {"PLUGIN_AUTHOR", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6663
  {"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6664
  {"PLUGIN_LICENSE", 80, MYSQL_TYPE_STRING, 0, 1, "License", SKIP_OPEN_TABLE},
 
6665
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6666
};
 
6667
 
 
6668
ST_FIELD_INFO files_fields_info[]=
 
6669
{
 
6670
  {"FILE_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE},
 
6671
  {"FILE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6672
  {"FILE_TYPE", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6673
  {"TABLESPACE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6674
   SKIP_OPEN_TABLE},
 
6675
  {"TABLE_CATALOG", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6676
  {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6677
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6678
  {"LOGFILE_GROUP_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6679
   SKIP_OPEN_TABLE},
 
6680
  {"LOGFILE_GROUP_NUMBER", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
 
6681
  {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6682
  {"FULLTEXT_KEYS", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6683
  {"DELETED_ROWS", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
 
6684
  {"UPDATE_COUNT", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
 
6685
  {"FREE_EXTENTS", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
 
6686
  {"TOTAL_EXTENTS", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
 
6687
  {"EXTENT_SIZE", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE},
 
6688
  {"INITIAL_SIZE", 21, MYSQL_TYPE_LONGLONG, 0,
 
6689
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
 
6690
  {"MAXIMUM_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, 
 
6691
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
 
6692
  {"AUTOEXTEND_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, 
 
6693
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
 
6694
  {"CREATION_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
 
6695
  {"LAST_UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
 
6696
  {"LAST_ACCESS_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, 0, SKIP_OPEN_TABLE},
 
6697
  {"RECOVER_TIME", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
 
6698
  {"TRANSACTION_COUNTER", 4, MYSQL_TYPE_LONGLONG, 0, 1, 0, SKIP_OPEN_TABLE},
 
6699
  {"VERSION", 21 , MYSQL_TYPE_LONGLONG, 0,
 
6700
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Version", SKIP_OPEN_TABLE},
 
6701
  {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format", SKIP_OPEN_TABLE},
 
6702
  {"TABLE_ROWS", 21 , MYSQL_TYPE_LONGLONG, 0,
 
6703
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Rows", SKIP_OPEN_TABLE},
 
6704
  {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, 
 
6705
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Avg_row_length", SKIP_OPEN_TABLE},
 
6706
  {"DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, 
 
6707
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_length", SKIP_OPEN_TABLE},
 
6708
  {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, 
 
6709
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_data_length", SKIP_OPEN_TABLE},
 
6710
  {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONGLONG, 0, 
 
6711
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Index_length", SKIP_OPEN_TABLE},
 
6712
  {"DATA_FREE", 21 , MYSQL_TYPE_LONGLONG, 0, 
 
6713
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Data_free", SKIP_OPEN_TABLE},
 
6714
  {"CREATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Create_time", SKIP_OPEN_TABLE},
 
6715
  {"UPDATE_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Update_time", SKIP_OPEN_TABLE},
 
6716
  {"CHECK_TIME", 0, MYSQL_TYPE_DATETIME, 0, 1, "Check_time", SKIP_OPEN_TABLE},
 
6717
  {"CHECKSUM", 21 , MYSQL_TYPE_LONGLONG, 0, 
 
6718
   (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Checksum", SKIP_OPEN_TABLE},
 
6719
  {"STATUS", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
 
6720
  {"EXTRA", 255, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
 
6721
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6722
};
 
6723
 
 
6724
void init_fill_schema_files_row(TABLE* table)
 
6725
{
 
6726
  int i;
 
6727
  for(i=0; files_fields_info[i].field_name!=NULL; i++)
 
6728
    table->field[i]->set_null();
 
6729
 
 
6730
  table->field[IS_FILES_STATUS]->set_notnull();
 
6731
  table->field[IS_FILES_STATUS]->store("NORMAL", 6, system_charset_info);
 
6732
}
 
6733
 
 
6734
ST_FIELD_INFO referential_constraints_fields_info[]=
 
6735
{
 
6736
  {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
 
6737
  {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6738
   OPEN_FULL_TABLE},
 
6739
  {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6740
   OPEN_FULL_TABLE},
 
6741
  {"UNIQUE_CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0,
 
6742
   OPEN_FULL_TABLE},
 
6743
  {"UNIQUE_CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6744
   OPEN_FULL_TABLE},
 
6745
  {"UNIQUE_CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0,
 
6746
   MY_I_S_MAYBE_NULL, 0, OPEN_FULL_TABLE},
 
6747
  {"MATCH_OPTION", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6748
  {"UPDATE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6749
  {"DELETE_RULE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6750
  {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
 
6751
  {"REFERENCED_TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
 
6752
   OPEN_FULL_TABLE},
 
6753
  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
 
6754
};
 
6755
 
 
6756
 
 
6757
/*
 
6758
  Description of ST_FIELD_INFO in table.h
 
6759
 
 
6760
  Make sure that the order of schema_tables and enum_schema_tables are the same.
 
6761
 
 
6762
*/
 
6763
 
 
6764
ST_SCHEMA_TABLE schema_tables[]=
 
6765
{
 
6766
  {"CHARACTER_SETS", charsets_fields_info, create_schema_table, 
 
6767
   fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0},
 
6768
  {"COLLATIONS", collation_fields_info, create_schema_table, 
 
6769
   fill_schema_collation, make_old_format, 0, -1, -1, 0, 0},
 
6770
  {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
 
6771
   create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1, 0, 0},
 
6772
  {"COLUMNS", columns_fields_info, create_schema_table, 
 
6773
   get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2, 0,
 
6774
   OPTIMIZE_I_S_TABLE|OPEN_VIEW_FULL},
 
6775
  {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table,
 
6776
   fill_schema_column_privileges, 0, 0, -1, -1, 0, 0},
 
6777
  {"ENGINES", engines_fields_info, create_schema_table,
 
6778
   fill_schema_engines, make_old_format, 0, -1, -1, 0, 0},
 
6779
#ifdef HAVE_EVENT_SCHEDULER
 
6780
  {"EVENTS", events_fields_info, create_schema_table,
 
6781
   Events::fill_schema_events, make_old_format, 0, -1, -1, 0, 0},
 
6782
#else
 
6783
  {"EVENTS", events_fields_info, create_schema_table,
 
6784
   0, make_old_format, 0, -1, -1, 0, 0},
 
6785
#endif
 
6786
  {"FILES", files_fields_info, create_schema_table,
 
6787
   fill_schema_files, 0, 0, -1, -1, 0, 0},
 
6788
  {"GLOBAL_STATUS", variables_fields_info, create_schema_table,
 
6789
   fill_status, make_old_format, 0, 0, -1, 0, 0},
 
6790
  {"GLOBAL_VARIABLES", variables_fields_info, create_schema_table,
 
6791
   fill_variables, make_old_format, 0, 0, -1, 0, 0},
 
6792
  {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
 
6793
   get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
 
6794
   OPEN_TABLE_ONLY},
 
6795
  {"OPEN_TABLES", open_tables_fields_info, create_schema_table,
 
6796
   fill_open_tables, make_old_format, 0, -1, -1, 1, 0},
 
6797
  {"PARTITIONS", partitions_fields_info, create_schema_table,
 
6798
   get_all_tables, 0, get_schema_partitions_record, 1, 2, 0, OPEN_TABLE_ONLY},
 
6799
  {"PLUGINS", plugin_fields_info, create_schema_table,
 
6800
   fill_plugins, make_old_format, 0, -1, -1, 0, 0},
 
6801
  {"PROCESSLIST", processlist_fields_info, create_schema_table,
 
6802
   fill_schema_processlist, make_old_format, 0, -1, -1, 0, 0},
 
6803
  {"PROFILING", query_profile_statistics_info, create_schema_table,
 
6804
    fill_query_profile_statistics_info, make_profile_table_for_show, 
 
6805
    NULL, -1, -1, false, 0},
 
6806
  {"REFERENTIAL_CONSTRAINTS", referential_constraints_fields_info,
 
6807
   create_schema_table, get_all_tables, 0, get_referential_constraints_record,
 
6808
   1, 9, 0, OPEN_TABLE_ONLY},
 
6809
  {"ROUTINES", proc_fields_info, create_schema_table, 
 
6810
   fill_schema_proc, make_proc_old_format, 0, -1, -1, 0, 0},
 
6811
  {"SCHEMATA", schema_fields_info, create_schema_table,
 
6812
   fill_schema_schemata, make_schemata_old_format, 0, 1, -1, 0, 0},
 
6813
  {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table,
 
6814
   fill_schema_schema_privileges, 0, 0, -1, -1, 0, 0},
 
6815
  {"SESSION_STATUS", variables_fields_info, create_schema_table,
 
6816
   fill_status, make_old_format, 0, 0, -1, 0, 0},
 
6817
  {"SESSION_VARIABLES", variables_fields_info, create_schema_table,
 
6818
   fill_variables, make_old_format, 0, 0, -1, 0, 0},
 
6819
  {"STATISTICS", stat_fields_info, create_schema_table, 
 
6820
   get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0,
 
6821
   OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE},
 
6822
  {"STATUS", variables_fields_info, create_schema_table, fill_status, 
 
6823
   make_old_format, 0, 0, -1, 1, 0},
 
6824
  {"TABLES", tables_fields_info, create_schema_table, 
 
6825
   get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0,
 
6826
   OPTIMIZE_I_S_TABLE},
 
6827
  {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table,
 
6828
   get_all_tables, 0, get_schema_constraints_record, 3, 4, 0, OPEN_TABLE_ONLY},
 
6829
  {"TABLE_NAMES", table_names_fields_info, create_schema_table,
 
6830
   get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
 
6831
  {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
 
6832
   fill_schema_table_privileges, 0, 0, -1, -1, 0, 0},
 
6833
  {"TRIGGERS", triggers_fields_info, create_schema_table,
 
6834
   get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0,
 
6835
   OPEN_TABLE_ONLY},
 
6836
  {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table, 
 
6837
   fill_schema_user_privileges, 0, 0, -1, -1, 0, 0},
 
6838
  {"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
 
6839
   make_old_format, 0, 0, -1, 1, 0},
 
6840
  {"VIEWS", view_fields_info, create_schema_table, 
 
6841
   get_all_tables, 0, get_schema_views_record, 1, 2, 0,
 
6842
   OPEN_VIEW_ONLY|OPTIMIZE_I_S_TABLE},
 
6843
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 
6844
};
 
6845
 
 
6846
 
 
6847
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
6848
template class List_iterator_fast<char>;
 
6849
template class List<char>;
 
6850
#endif
 
6851
 
 
6852
int initialize_schema_table(st_plugin_int *plugin)
 
6853
{
 
6854
  ST_SCHEMA_TABLE *schema_table;
 
6855
  DBUG_ENTER("initialize_schema_table");
 
6856
 
 
6857
  if (!(schema_table= (ST_SCHEMA_TABLE *)my_malloc(sizeof(ST_SCHEMA_TABLE),
 
6858
                                MYF(MY_WME | MY_ZEROFILL))))
 
6859
      DBUG_RETURN(1);
 
6860
  /* Historical Requirement */
 
6861
  plugin->data= schema_table; // shortcut for the future
 
6862
  if (plugin->plugin->init)
 
6863
  {
 
6864
    schema_table->create_table= create_schema_table;
 
6865
    schema_table->old_format= make_old_format;
 
6866
    schema_table->idx_field1= -1, 
 
6867
    schema_table->idx_field2= -1; 
 
6868
 
 
6869
    /* Make the name available to the init() function. */
 
6870
    schema_table->table_name= plugin->name.str;
 
6871
 
 
6872
    if (plugin->plugin->init(schema_table))
 
6873
    {
 
6874
      sql_print_error("Plugin '%s' init function returned error.",
 
6875
                      plugin->name.str);
 
6876
      plugin->data= NULL;
 
6877
      my_free(schema_table, MYF(0));
 
6878
      DBUG_RETURN(1);
 
6879
    }
 
6880
    
 
6881
    /* Make sure the plugin name is not set inside the init() function. */
 
6882
    schema_table->table_name= plugin->name.str;
 
6883
  }
 
6884
  DBUG_RETURN(0);
 
6885
}
 
6886
 
 
6887
int finalize_schema_table(st_plugin_int *plugin)
 
6888
{
 
6889
  ST_SCHEMA_TABLE *schema_table= (ST_SCHEMA_TABLE *)plugin->data;
 
6890
  DBUG_ENTER("finalize_schema_table");
 
6891
 
 
6892
  if (schema_table && plugin->plugin->deinit)
 
6893
  {
 
6894
    DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
 
6895
    if (plugin->plugin->deinit(NULL))
 
6896
    {
 
6897
      DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
 
6898
                             plugin->name.str));
 
6899
    }
 
6900
    my_free(schema_table, MYF(0));
 
6901
  }
 
6902
  DBUG_RETURN(0);
 
6903
}
 
6904
 
 
6905
 
 
6906
/**
 
6907
  Output trigger information (SHOW CREATE TRIGGER) to the client.
 
6908
 
 
6909
  @param thd          Thread context.
 
6910
  @param triggers     List of triggers for the table.
 
6911
  @param trigger_idx  Index of the trigger to dump.
 
6912
 
 
6913
  @return Operation status
 
6914
    @retval TRUE Error.
 
6915
    @retval FALSE Success.
 
6916
*/
 
6917
 
 
6918
static bool show_create_trigger_impl(THD *thd,
 
6919
                                     Table_triggers_list *triggers,
 
6920
                                     int trigger_idx)
 
6921
{
 
6922
  int ret_code;
 
6923
 
 
6924
  Protocol *p= thd->protocol;
 
6925
  List<Item> fields;
 
6926
 
 
6927
  LEX_STRING trg_name;
 
6928
  ulonglong trg_sql_mode;
 
6929
  LEX_STRING trg_sql_mode_str;
 
6930
  LEX_STRING trg_sql_original_stmt;
 
6931
  LEX_STRING trg_client_cs_name;
 
6932
  LEX_STRING trg_connection_cl_name;
 
6933
  LEX_STRING trg_db_cl_name;
 
6934
 
 
6935
  CHARSET_INFO *trg_client_cs;
 
6936
 
 
6937
  /*
 
6938
    TODO: Check privileges here. This functionality will be added by
 
6939
    implementation of the following WL items:
 
6940
      - WL#2227: New privileges for new objects
 
6941
      - WL#3482: Protect SHOW CREATE PROCEDURE | FUNCTION | VIEW | TRIGGER
 
6942
        properly
 
6943
 
 
6944
    SHOW TRIGGERS and I_S.TRIGGERS will be affected too.
 
6945
  */
 
6946
 
 
6947
  /* Prepare trigger "object". */
 
6948
 
 
6949
  triggers->get_trigger_info(thd,
 
6950
                             trigger_idx,
 
6951
                             &trg_name,
 
6952
                             &trg_sql_mode,
 
6953
                             &trg_sql_original_stmt,
 
6954
                             &trg_client_cs_name,
 
6955
                             &trg_connection_cl_name,
 
6956
                             &trg_db_cl_name);
 
6957
 
 
6958
  sys_var_thd_sql_mode::symbolic_mode_representation(thd,
 
6959
                                                     trg_sql_mode,
 
6960
                                                     &trg_sql_mode_str);
 
6961
 
 
6962
  /* Resolve trigger client character set. */
 
6963
 
 
6964
  if (resolve_charset(trg_client_cs_name.str, NULL, &trg_client_cs))
 
6965
    return TRUE;
 
6966
 
 
6967
  /* Send header. */
 
6968
 
 
6969
  fields.push_back(new Item_empty_string("Trigger", NAME_LEN));
 
6970
  fields.push_back(new Item_empty_string("sql_mode", trg_sql_mode_str.length));
 
6971
 
 
6972
  {
 
6973
    /*
 
6974
      NOTE: SQL statement field must be not less than 1024 in order not to
 
6975
      confuse old clients.
 
6976
    */
 
6977
 
 
6978
    Item_empty_string *stmt_fld=
 
6979
      new Item_empty_string("SQL Original Statement",
 
6980
                            max(trg_sql_original_stmt.length, 1024));
 
6981
 
 
6982
    stmt_fld->maybe_null= TRUE;
 
6983
 
 
6984
    fields.push_back(stmt_fld);
 
6985
  }
 
6986
 
 
6987
  fields.push_back(new Item_empty_string("character_set_client",
 
6988
                                         MY_CS_NAME_SIZE));
 
6989
 
 
6990
  fields.push_back(new Item_empty_string("collation_connection",
 
6991
                                         MY_CS_NAME_SIZE));
 
6992
 
 
6993
  fields.push_back(new Item_empty_string("Database Collation",
 
6994
                                         MY_CS_NAME_SIZE));
 
6995
 
 
6996
  if (p->send_fields(&fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 
6997
    return TRUE;
 
6998
 
 
6999
  /* Send data. */
 
7000
 
 
7001
  p->prepare_for_resend();
 
7002
 
 
7003
  p->store(trg_name.str,
 
7004
           trg_name.length,
 
7005
           system_charset_info);
 
7006
 
 
7007
  p->store(trg_sql_mode_str.str,
 
7008
           trg_sql_mode_str.length,
 
7009
           system_charset_info);
 
7010
 
 
7011
  p->store(trg_sql_original_stmt.str,
 
7012
           trg_sql_original_stmt.length,
 
7013
           trg_client_cs);
 
7014
 
 
7015
  p->store(trg_client_cs_name.str,
 
7016
           trg_client_cs_name.length,
 
7017
           system_charset_info);
 
7018
 
 
7019
  p->store(trg_connection_cl_name.str,
 
7020
           trg_connection_cl_name.length,
 
7021
           system_charset_info);
 
7022
 
 
7023
  p->store(trg_db_cl_name.str,
 
7024
           trg_db_cl_name.length,
 
7025
           system_charset_info);
 
7026
 
 
7027
  ret_code= p->write();
 
7028
 
 
7029
  if (!ret_code)
 
7030
    my_eof(thd);
 
7031
 
 
7032
  return ret_code != 0;
 
7033
}
 
7034
 
 
7035
 
 
7036
/**
 
7037
  Read TRN and TRG files to obtain base table name for the specified
 
7038
  trigger name and construct TABE_LIST object for the base table.
 
7039
 
 
7040
  @param thd      Thread context.
 
7041
  @param trg_name Trigger name.
 
7042
 
 
7043
  @return TABLE_LIST object corresponding to the base table.
 
7044
 
 
7045
  TODO: This function is a copy&paste from add_table_to_list() and
 
7046
  sp_add_to_query_tables(). The problem is that in order to be compatible
 
7047
  with Stored Programs (Prepared Statements), we should not touch thd->lex.
 
7048
  The "source" functions also add created TABLE_LIST object to the
 
7049
  thd->lex->query_tables.
 
7050
 
 
7051
  The plan to eliminate this copy&paste is to:
 
7052
 
 
7053
    - get rid of sp_add_to_query_tables() and use Lex::add_table_to_list().
 
7054
      Only add_table_to_list() must be used to add tables from the parser
 
7055
      into Lex::query_tables list.
 
7056
 
 
7057
    - do not update Lex::query_tables in add_table_to_list().
 
7058
*/
 
7059
 
 
7060
static TABLE_LIST *get_trigger_table_impl(
 
7061
  THD *thd,
 
7062
  const sp_name *trg_name)
 
7063
{
 
7064
  char trn_path_buff[FN_REFLEN];
 
7065
 
 
7066
  LEX_STRING trn_path= { trn_path_buff, 0 };
 
7067
  LEX_STRING tbl_name;
 
7068
 
 
7069
  build_trn_path(thd, trg_name, &trn_path);
 
7070
 
 
7071
  if (check_trn_exists(&trn_path))
 
7072
  {
 
7073
    my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
 
7074
    return NULL;
 
7075
  }
 
7076
 
 
7077
  if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name))
 
7078
    return NULL;
 
7079
 
 
7080
  /* We need to reset statement table list to be PS/SP friendly. */
 
7081
 
 
7082
  TABLE_LIST *table;
 
7083
 
 
7084
  if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST))))
 
7085
  {
 
7086
    my_error(ER_OUTOFMEMORY, MYF(0), sizeof(TABLE_LIST));
 
7087
    return NULL;
 
7088
  }
 
7089
 
 
7090
  table->db_length= trg_name->m_db.length;
 
7091
  table->db= thd->strmake(trg_name->m_db.str, trg_name->m_db.length);
 
7092
 
 
7093
  table->table_name_length= tbl_name.length;
 
7094
  table->table_name= thd->strmake(tbl_name.str, tbl_name.length);
 
7095
 
 
7096
  table->alias= thd->strmake(tbl_name.str, tbl_name.length);
 
7097
 
 
7098
  table->lock_type= TL_IGNORE;
 
7099
  table->cacheable_table= 0;
 
7100
 
 
7101
  return table;
 
7102
}
 
7103
 
 
7104
/**
 
7105
  Read TRN and TRG files to obtain base table name for the specified
 
7106
  trigger name and construct TABE_LIST object for the base table. Acquire
 
7107
  LOCK_open when doing this.
 
7108
 
 
7109
  @param thd      Thread context.
 
7110
  @param trg_name Trigger name.
 
7111
 
 
7112
  @return TABLE_LIST object corresponding to the base table.
 
7113
*/
 
7114
 
 
7115
static TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name)
 
7116
{
 
7117
  /* Acquire LOCK_open (stop the server). */
 
7118
 
 
7119
  pthread_mutex_lock(&LOCK_open);
 
7120
 
 
7121
  /*
 
7122
    Load base table name from the TRN-file and create TABLE_LIST object.
 
7123
  */
 
7124
 
 
7125
  TABLE_LIST *lst= get_trigger_table_impl(thd, trg_name);
 
7126
 
 
7127
  /* Release LOCK_open (continue the server). */
 
7128
 
 
7129
  pthread_mutex_unlock(&LOCK_open);
 
7130
 
 
7131
  /* That's it. */
 
7132
 
 
7133
  return lst;
 
7134
}
 
7135
 
 
7136
 
 
7137
/**
 
7138
  SHOW CREATE TRIGGER high-level implementation.
 
7139
 
 
7140
  @param thd      Thread context.
 
7141
  @param trg_name Trigger name.
 
7142
 
 
7143
  @return Operation status
 
7144
    @retval TRUE Error.
 
7145
    @retval FALSE Success.
 
7146
*/
 
7147
 
 
7148
bool show_create_trigger(THD *thd, const sp_name *trg_name)
 
7149
{
 
7150
  TABLE_LIST *lst= get_trigger_table(thd, trg_name);
 
7151
 
 
7152
  if (!lst)
 
7153
    return TRUE;
 
7154
 
 
7155
  if (check_table_access(thd, TRIGGER_ACL, lst, 1, TRUE))
 
7156
  {
 
7157
    my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "TRIGGER");
 
7158
    return TRUE;
 
7159
  }
 
7160
 
 
7161
  /*
 
7162
    Open the table by name in order to load Table_triggers_list object.
 
7163
 
 
7164
    NOTE: there is race condition here -- the table can be dropped after
 
7165
    LOCK_open is released. It will be fixed later by introducing
 
7166
    acquire-shared-table-name-lock functionality.
 
7167
  */
 
7168
 
 
7169
  uint num_tables; /* NOTE: unused, only to pass to open_tables(). */
 
7170
 
 
7171
  if (open_tables(thd, &lst, &num_tables, 0))
 
7172
  {
 
7173
    my_error(ER_TRG_CANT_OPEN_TABLE, MYF(0),
 
7174
             (const char *) trg_name->m_db.str,
 
7175
             (const char *) lst->table_name);
 
7176
 
 
7177
    return TRUE;
 
7178
 
 
7179
    /* Perform closing actions and return error status. */
 
7180
  }
 
7181
 
 
7182
  Table_triggers_list *triggers= lst->table->triggers;
 
7183
 
 
7184
  if (!triggers)
 
7185
  {
 
7186
    my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
 
7187
    return TRUE;
 
7188
  }
 
7189
 
 
7190
  int trigger_idx= triggers->find_trigger_by_name(&trg_name->m_name);
 
7191
 
 
7192
  if (trigger_idx < 0)
 
7193
  {
 
7194
    my_error(ER_TRG_CORRUPTED_FILE, MYF(0),
 
7195
             (const char *) trg_name->m_db.str,
 
7196
             (const char *) lst->table_name);
 
7197
 
 
7198
    return TRUE;
 
7199
  }
 
7200
 
 
7201
  return show_create_trigger_impl(thd, triggers, trigger_idx);
 
7202
 
 
7203
  /*
 
7204
    NOTE: if show_create_trigger_impl() failed, that means we could not
 
7205
    send data to the client. In this case we simply raise the error
 
7206
    status and client connection will be closed.
 
7207
  */
 
7208
}