~drizzle-trunk/drizzle/development

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