~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Monty Taylor
  • Date: 2009-09-22 23:50:12 UTC
  • mto: This revision was merged to the branch mainline in revision 1184.
  • Revision ID: mordred@inaugust.com-20090922235012-i0a3bs91f6krqduc
Fixed multi_malloc.h include guard.
Added include guard checking script.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
 
21
21
/* Function with list databases, tables or fields */
22
 
#include "config.h"
 
22
#include <drizzled/server_includes.h>
23
23
#include <drizzled/sql_select.h>
24
24
#include <drizzled/show.h>
25
25
#include <drizzled/gettext.h>
39
39
#include <drizzled/lock.h>
40
40
#include <drizzled/item/return_date_time.h>
41
41
#include <drizzled/item/empty_string.h>
42
 
#include "drizzled/session/cache.h"
 
42
#include "drizzled/plugin/registry.h"
 
43
#include <drizzled/plugin/info_schema.h>
43
44
#include <drizzled/message/schema.pb.h>
44
 
#include <drizzled/plugin/client.h>
45
 
#include <drizzled/cached_directory.h>
46
 
#include "drizzled/sql_table.h"
47
 
#include "drizzled/global_charset_info.h"
48
 
#include "drizzled/pthread_globals.h"
49
 
#include "drizzled/internal/m_string.h"
50
 
#include "drizzled/internal/my_sys.h"
51
 
#include "drizzled/message/statement_transform.h"
52
 
 
53
 
 
 
45
#include <mysys/cached_directory.h>
54
46
#include <sys/stat.h>
55
47
 
56
48
#include <string>
60
52
#include <algorithm>
61
53
 
62
54
using namespace std;
 
55
using namespace drizzled;
63
56
 
64
 
namespace drizzled
65
 
{
 
57
extern "C"
 
58
int show_var_cmp(const void *var1, const void *var2);
66
59
 
67
60
inline const char *
68
61
str_or_nil(const char *str)
70
63
  return str ? str : "<nil>";
71
64
}
72
65
 
73
 
int wild_case_compare(const CHARSET_INFO * const cs, const char *str, const char *wildstr)
 
66
static void store_key_options(String *packet, Table *table, KEY *key_info);
 
67
 
 
68
 
 
69
 
 
70
int wild_case_compare(const CHARSET_INFO * const cs, const char *str,const char *wildstr)
74
71
{
75
72
  register int flag;
76
 
 
77
73
  while (*wildstr)
78
74
  {
79
 
    while (*wildstr && *wildstr != internal::wild_many && *wildstr != internal::wild_one)
 
75
    while (*wildstr && *wildstr != wild_many && *wildstr != wild_one)
80
76
    {
81
 
      if (*wildstr == internal::wild_prefix && wildstr[1])
 
77
      if (*wildstr == wild_prefix && wildstr[1])
82
78
        wildstr++;
83
79
      if (my_toupper(cs, *wildstr++) != my_toupper(cs, *str++))
84
80
        return (1);
85
81
    }
86
82
    if (! *wildstr )
87
83
      return (*str != 0);
88
 
    if (*wildstr++ == internal::wild_one)
 
84
    if (*wildstr++ == wild_one)
89
85
    {
90
86
      if (! *str++)
91
87
        return (1);     /* One char; skip */
94
90
    {                                           /* Found '*' */
95
91
      if (! *wildstr)
96
92
        return (0);             /* '*' as last char: OK */
97
 
      flag=(*wildstr != internal::wild_many && *wildstr != internal::wild_one);
 
93
      flag=(*wildstr != wild_many && *wildstr != wild_one);
98
94
      do
99
95
      {
100
96
        if (flag)
101
97
        {
102
98
          char cmp;
103
 
          if ((cmp= *wildstr) == internal::wild_prefix && wildstr[1])
 
99
          if ((cmp= *wildstr) == wild_prefix && wildstr[1])
104
100
            cmp= wildstr[1];
105
101
          cmp= my_toupper(cs, cmp);
106
102
          while (*str && my_toupper(cs, *str) != cmp)
114
110
      return (1);
115
111
    }
116
112
  }
117
 
 
118
113
  return (*str != '\0');
119
114
}
120
115
 
 
116
 
 
117
/**
 
118
 * @brief
 
119
 *   Find subdirectories (schemas) in a given directory (datadir).
 
120
 *
 
121
 * @param[in]  session    Thread handler
 
122
 * @param[out] files      Put found entries in this list
 
123
 * @param[in]  path       Path to database
 
124
 * @param[in]  wild       Filter for found entries
 
125
 *
 
126
 * @retval false   Success
 
127
 * @retval true    Error
 
128
 */
 
129
static bool find_schemas(Session *session, vector<LEX_STRING*> &files,
 
130
                         const char *path, const char *wild)
 
131
{
 
132
  if (wild && (wild[0] == '\0'))
 
133
    wild= 0;
 
134
 
 
135
  CachedDirectory directory(path);
 
136
 
 
137
  if (directory.fail())
 
138
  {
 
139
    my_errno= directory.getError();
 
140
    my_error(ER_CANT_READ_DIR, MYF(0), path, my_errno);
 
141
    return(true);
 
142
  }
 
143
 
 
144
  CachedDirectory::Entries entries= directory.getEntries();
 
145
  CachedDirectory::Entries::iterator entry_iter= entries.begin();
 
146
 
 
147
  while (entry_iter != entries.end())
 
148
  {
 
149
    uint32_t file_name_len;
 
150
    char uname[NAME_LEN + 1];                   /* Unencoded name */
 
151
    struct stat entry_stat;
 
152
    CachedDirectory::Entry *entry= *entry_iter;
 
153
 
 
154
    if ((entry->filename == ".") || (entry->filename == ".."))
 
155
    {
 
156
      ++entry_iter;
 
157
      continue;
 
158
    }
 
159
 
 
160
    if (stat(entry->filename.c_str(), &entry_stat))
 
161
    {
 
162
      my_errno= errno;
 
163
      my_error(ER_CANT_GET_STAT, MYF(0), entry->filename.c_str(), my_errno);
 
164
      return(true);
 
165
    }
 
166
 
 
167
    if (! S_ISDIR(entry_stat.st_mode))
 
168
    {
 
169
      ++entry_iter;
 
170
      continue;
 
171
    }
 
172
 
 
173
    file_name_len= filename_to_tablename(entry->filename.c_str(), uname,
 
174
                                         sizeof(uname));
 
175
    if (wild && wild_compare(uname, wild, 0))
 
176
    {
 
177
      ++entry_iter;
 
178
      continue;
 
179
    }
 
180
 
 
181
    LEX_STRING *file_name= 0;
 
182
    file_name= session->make_lex_string(file_name, uname, file_name_len, true);
 
183
    if (file_name == NULL)
 
184
      return(true);
 
185
 
 
186
    files.push_back(file_name);
 
187
    ++entry_iter;
 
188
  }
 
189
 
 
190
  return(false);
 
191
}
 
192
 
 
193
 
 
194
bool drizzled_show_create(Session *session, TableList *table_list)
 
195
{
 
196
  plugin::Protocol *protocol= session->protocol;
 
197
  char buff[2048];
 
198
  String buffer(buff, sizeof(buff), system_charset_info);
 
199
 
 
200
  /* Only one table for now, but VIEW can involve several tables */
 
201
  if (session->openTables(table_list))
 
202
  {
 
203
    if (session->is_error())
 
204
      return true;
 
205
 
 
206
    /*
 
207
      Clear all messages with 'error' level status and
 
208
      issue a warning with 'warning' level status in
 
209
      case of invalid view and last error is ER_VIEW_INVALID
 
210
    */
 
211
    drizzle_reset_errors(session, true);
 
212
    session->clear_error();
 
213
  }
 
214
 
 
215
  buffer.length(0);
 
216
 
 
217
  if (store_create_info(table_list, &buffer, NULL))
 
218
    return true;
 
219
 
 
220
  List<Item> field_list;
 
221
  {
 
222
    field_list.push_back(new Item_empty_string("Table",NAME_CHAR_LEN));
 
223
    // 1024 is for not to confuse old clients
 
224
    field_list.push_back(new Item_empty_string("Create Table",
 
225
                                               max(buffer.length(),(uint32_t)1024)));
 
226
  }
 
227
 
 
228
  if (protocol->sendFields(&field_list))
 
229
    return true;
 
230
  protocol->prepareForResend();
 
231
  {
 
232
    if (table_list->schema_table)
 
233
      protocol->store(table_list->schema_table->getTableName().c_str());
 
234
    else
 
235
      protocol->store(table_list->table->alias);
 
236
  }
 
237
 
 
238
  protocol->store(buffer.ptr(), buffer.length());
 
239
 
 
240
  if (protocol->write())
 
241
    return true;
 
242
 
 
243
  session->my_eof();
 
244
  return false;
 
245
}
 
246
 
 
247
/**
 
248
  Get a CREATE statement for a given database.
 
249
 
 
250
  The database is identified by its name, passed as @c dbname parameter.
 
251
  The name should be encoded using the system character set (UTF8 currently).
 
252
 
 
253
  Resulting statement is stored in the string pointed by @c buffer. The string
 
254
  is emptied first and its character set is set to the system character set.
 
255
 
 
256
  If HA_LEX_CREATE_IF_NOT_EXISTS flag is set in @c create_info->options, then
 
257
  the resulting CREATE statement contains "IF NOT EXISTS" clause. Other flags
 
258
  in @c create_options are ignored.
 
259
 
 
260
  @param  session           The current thread instance.
 
261
  @param  dbname        The name of the database.
 
262
  @param  buffer        A String instance where the statement is stored.
 
263
  @param  create_info   If not NULL, the options member influences the resulting
 
264
                        CRATE statement.
 
265
 
 
266
  @returns true if errors are detected, false otherwise.
 
267
*/
 
268
 
 
269
static bool store_db_create_info(const char *dbname, String *buffer, bool if_not_exists)
 
270
{
 
271
  message::Schema schema;
 
272
 
 
273
  if (!my_strcasecmp(system_charset_info, dbname,
 
274
                     INFORMATION_SCHEMA_NAME.c_str()))
 
275
  {
 
276
    dbname= INFORMATION_SCHEMA_NAME.c_str();
 
277
  }
 
278
  else
 
279
  {
 
280
    int r= get_database_metadata(dbname, &schema);
 
281
    if(r < 0)
 
282
      return true;
 
283
  }
 
284
 
 
285
  buffer->length(0);
 
286
  buffer->free();
 
287
  buffer->set_charset(system_charset_info);
 
288
  buffer->append(STRING_WITH_LEN("CREATE DATABASE "));
 
289
 
 
290
  if (if_not_exists)
 
291
    buffer->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
292
 
 
293
  buffer->append_identifier(dbname, strlen(dbname));
 
294
 
 
295
  if (schema.has_collation() && strcmp(schema.collation().c_str(),
 
296
                                       default_charset_info->name))
 
297
  {
 
298
    buffer->append(" COLLATE = ");
 
299
    buffer->append(schema.collation().c_str());
 
300
  }
 
301
 
 
302
  return false;
 
303
}
 
304
 
 
305
bool mysqld_show_create_db(Session *session, char *dbname, bool if_not_exists)
 
306
{
 
307
  char buff[2048];
 
308
  String buffer(buff, sizeof(buff), system_charset_info);
 
309
  plugin::Protocol *protocol= session->protocol;
 
310
 
 
311
  if (store_db_create_info(dbname, &buffer, if_not_exists))
 
312
  {
 
313
    /*
 
314
      This assumes that the only reason for which store_db_create_info()
 
315
      can fail is incorrect database name (which is the case now).
 
316
    */
 
317
    my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
 
318
    return true;
 
319
  }
 
320
 
 
321
  List<Item> field_list;
 
322
  field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
 
323
  field_list.push_back(new Item_empty_string("Create Database",1024));
 
324
 
 
325
  if (protocol->sendFields(&field_list))
 
326
    return true;
 
327
 
 
328
  protocol->prepareForResend();
 
329
  protocol->store(dbname, strlen(dbname));
 
330
  protocol->store(buffer.ptr(), buffer.length());
 
331
 
 
332
  if (protocol->write())
 
333
    return true;
 
334
  session->my_eof();
 
335
  return false;
 
336
}
 
337
 
121
338
/*
122
339
  Get the quote character for displaying an identifier.
123
340
 
143
360
  return '`';
144
361
}
145
362
 
146
 
} /* namespace drizzled */
 
363
 
 
364
#define LIST_PROCESS_HOST_LEN 64
 
365
 
 
366
static bool get_field_default_value(Field *timestamp_field,
 
367
                                    Field *field, String *def_value,
 
368
                                    bool quoted)
 
369
{
 
370
  bool has_default;
 
371
  bool has_now_default;
 
372
 
 
373
  /*
 
374
     We are using CURRENT_TIMESTAMP instead of NOW because it is
 
375
     more standard
 
376
  */
 
377
  has_now_default= (timestamp_field == field &&
 
378
                    field->unireg_check != Field::TIMESTAMP_UN_FIELD);
 
379
 
 
380
  has_default= (field->type() != DRIZZLE_TYPE_BLOB &&
 
381
                !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
 
382
                field->unireg_check != Field::NEXT_NUMBER);
 
383
 
 
384
  def_value->length(0);
 
385
  if (has_default)
 
386
  {
 
387
    if (has_now_default)
 
388
      def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
 
389
    else if (!field->is_null())
 
390
    {                                             // Not null by default
 
391
      char tmp[MAX_FIELD_WIDTH];
 
392
      String type(tmp, sizeof(tmp), field->charset());
 
393
      field->val_str(&type);
 
394
      if (type.length())
 
395
      {
 
396
        String def_val;
 
397
        uint32_t dummy_errors;
 
398
        /* convert to system_charset_info == utf8 */
 
399
        def_val.copy(type.ptr(), type.length(), field->charset(),
 
400
                     system_charset_info, &dummy_errors);
 
401
        if (quoted)
 
402
          append_unescaped(def_value, def_val.ptr(), def_val.length());
 
403
        else
 
404
          def_value->append(def_val.ptr(), def_val.length());
 
405
      }
 
406
      else if (quoted)
 
407
        def_value->append(STRING_WITH_LEN("''"));
 
408
    }
 
409
    else if (field->maybe_null() && quoted)
 
410
      def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
 
411
    else
 
412
      return false;
 
413
  }
 
414
  return has_default;
 
415
}
 
416
 
 
417
/*
 
418
  Build a CREATE TABLE statement for a table.
 
419
 
 
420
  SYNOPSIS
 
421
    store_create_info()
 
422
    table_list        A list containing one table to write statement
 
423
                      for.
 
424
    packet            Pointer to a string where statement will be
 
425
                      written.
 
426
    create_info_arg   Pointer to create information that can be used
 
427
                      to tailor the format of the statement.  Can be
 
428
                      NULL, in which case only SQL_MODE is considered
 
429
                      when building the statement.
 
430
 
 
431
  NOTE
 
432
    Currently always return 0, but might return error code in the
 
433
    future.
 
434
 
 
435
  RETURN
 
436
    0       OK
 
437
 */
 
438
 
 
439
int store_create_info(TableList *table_list, String *packet, HA_CREATE_INFO *create_info_arg)
 
440
{
 
441
  List<Item> field_list;
 
442
  char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
 
443
  const char *alias;
 
444
  string buff;
 
445
  String type(tmp, sizeof(tmp), system_charset_info);
 
446
  String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
 
447
  Field **ptr,*field;
 
448
  uint32_t primary_key;
 
449
  KEY *key_info;
 
450
  Table *table= table_list->table;
 
451
  handler *file= table->file;
 
452
  TableShare *share= table->s;
 
453
  HA_CREATE_INFO create_info;
 
454
  bool show_table_options= false;
 
455
  my_bitmap_map *old_map;
 
456
 
 
457
  table->restoreRecordAsDefault(); // Get empty record
 
458
 
 
459
  if (share->tmp_table)
 
460
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
 
461
  else
 
462
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
 
463
  if (create_info_arg &&
 
464
      (create_info_arg->options & HA_LEX_CREATE_IF_NOT_EXISTS))
 
465
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
 
466
  if (table_list->schema_table)
 
467
    alias= table_list->schema_table->getTableName().c_str();
 
468
  else
 
469
    alias= share->table_name.str;
 
470
 
 
471
  packet->append_identifier(alias, strlen(alias));
 
472
  packet->append(STRING_WITH_LEN(" (\n"));
 
473
  /*
 
474
    We need this to get default values from the table
 
475
    We have to restore the read_set if we are called from insert in case
 
476
    of row based replication.
 
477
  */
 
478
  old_map= table->use_all_columns(table->read_set);
 
479
 
 
480
  for (ptr=table->field ; (field= *ptr); ptr++)
 
481
  {
 
482
    uint32_t flags = field->flags;
 
483
 
 
484
    if (ptr != table->field)
 
485
      packet->append(STRING_WITH_LEN(",\n"));
 
486
 
 
487
    packet->append(STRING_WITH_LEN("  "));
 
488
    packet->append_identifier(field->field_name, strlen(field->field_name));
 
489
    packet->append(' ');
 
490
    // check for surprises from the previous call to Field::sql_type()
 
491
    if (type.ptr() != tmp)
 
492
      type.set(tmp, sizeof(tmp), system_charset_info);
 
493
    else
 
494
      type.set_charset(system_charset_info);
 
495
 
 
496
    field->sql_type(type);
 
497
    packet->append(type.ptr(), type.length(), system_charset_info);
 
498
 
 
499
    if (field->has_charset())
 
500
    {
 
501
      if (field->charset() != share->table_charset)
 
502
      {
 
503
        packet->append(STRING_WITH_LEN(" CHARACTER SET "));
 
504
        packet->append(field->charset()->csname);
 
505
      }
 
506
 
 
507
      /*
 
508
        For string types dump collation name only if
 
509
        collation is not primary for the given charset
 
510
      */
 
511
      if (!(field->charset()->state & MY_CS_PRIMARY))
 
512
      {
 
513
        packet->append(STRING_WITH_LEN(" COLLATE "));
 
514
        packet->append(field->charset()->name);
 
515
      }
 
516
    }
 
517
 
 
518
    if (flags & NOT_NULL_FLAG)
 
519
      packet->append(STRING_WITH_LEN(" NOT NULL"));
 
520
    else if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
 
521
    {
 
522
      /*
 
523
        TIMESTAMP field require explicit NULL flag, because unlike
 
524
        all other fields they are treated as NOT NULL by default.
 
525
      */
 
526
      packet->append(STRING_WITH_LEN(" NULL"));
 
527
    }
 
528
    {
 
529
      /*
 
530
        Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
 
531
        and about STORAGE (DISK or MEMORY).
 
532
      */
 
533
      enum column_format_type column_format= (enum column_format_type)
 
534
        ((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
 
535
      if (column_format)
 
536
      {
 
537
        packet->append(STRING_WITH_LEN(" /*!"));
 
538
        packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
 
539
        if (column_format == COLUMN_FORMAT_TYPE_FIXED)
 
540
          packet->append(STRING_WITH_LEN(" FIXED */"));
 
541
        else
 
542
          packet->append(STRING_WITH_LEN(" DYNAMIC */"));
 
543
      }
 
544
    }
 
545
    if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
 
546
    {
 
547
      packet->append(STRING_WITH_LEN(" DEFAULT "));
 
548
      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
 
549
    }
 
550
 
 
551
    if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
552
      packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
 
553
 
 
554
    if (field->unireg_check == Field::NEXT_NUMBER)
 
555
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
 
556
 
 
557
    if (field->comment.length)
 
558
    {
 
559
      packet->append(STRING_WITH_LEN(" COMMENT "));
 
560
      append_unescaped(packet, field->comment.str, field->comment.length);
 
561
    }
 
562
  }
 
563
 
 
564
  key_info= table->key_info;
 
565
  memset(&create_info, 0, sizeof(create_info));
 
566
  /* Allow update_create_info to update row type */
 
567
  create_info.row_type= share->row_type;
 
568
  file->update_create_info(&create_info);
 
569
  primary_key= share->primary_key;
 
570
 
 
571
  for (uint32_t i=0 ; i < share->keys ; i++,key_info++)
 
572
  {
 
573
    KEY_PART_INFO *key_part= key_info->key_part;
 
574
    bool found_primary=0;
 
575
    packet->append(STRING_WITH_LEN(",\n  "));
 
576
 
 
577
    if (i == primary_key && is_primary_key(key_info))
 
578
    {
 
579
      found_primary=1;
 
580
      /*
 
581
        No space at end, because a space will be added after where the
 
582
        identifier would go, but that is not added for primary key.
 
583
      */
 
584
      packet->append(STRING_WITH_LEN("PRIMARY KEY"));
 
585
    }
 
586
    else if (key_info->flags & HA_NOSAME)
 
587
      packet->append(STRING_WITH_LEN("UNIQUE KEY "));
 
588
    else
 
589
      packet->append(STRING_WITH_LEN("KEY "));
 
590
 
 
591
    if (!found_primary)
 
592
     packet->append_identifier(key_info->name, strlen(key_info->name));
 
593
 
 
594
    packet->append(STRING_WITH_LEN(" ("));
 
595
 
 
596
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
 
597
    {
 
598
      if (j)
 
599
        packet->append(',');
 
600
 
 
601
      if (key_part->field)
 
602
        packet->append_identifier(key_part->field->field_name,
 
603
                                  strlen(key_part->field->field_name));
 
604
      if (key_part->field &&
 
605
          (key_part->length !=
 
606
           table->field[key_part->fieldnr-1]->key_length()))
 
607
      {
 
608
        buff.assign("(");
 
609
        buff.append(to_string((int32_t) key_part->length /
 
610
                              key_part->field->charset()->mbmaxlen));
 
611
        buff.append(")");
 
612
        packet->append(buff.c_str(), buff.length());
 
613
      }
 
614
    }
 
615
    packet->append(')');
 
616
    store_key_options(packet, table, key_info);
 
617
  }
 
618
 
 
619
  /*
 
620
    Get possible foreign key definitions stored in InnoDB and append them
 
621
    to the CREATE TABLE statement
 
622
  */
 
623
 
 
624
  if ((for_str= file->get_foreign_key_create_info()))
 
625
  {
 
626
    packet->append(for_str, strlen(for_str));
 
627
    file->free_foreign_key_create_info(for_str);
 
628
  }
 
629
 
 
630
  packet->append(STRING_WITH_LEN("\n)"));
 
631
  {
 
632
    show_table_options= true;
 
633
    /*
 
634
      Get possible table space definitions and append them
 
635
      to the CREATE TABLE statement
 
636
    */
 
637
 
 
638
    /*
 
639
      IF   check_create_info
 
640
      THEN add ENGINE only if it was used when creating the table
 
641
    */
 
642
    if (!create_info_arg ||
 
643
        (create_info_arg->used_fields & HA_CREATE_USED_ENGINE))
 
644
    {
 
645
      packet->append(STRING_WITH_LEN(" ENGINE="));
 
646
      packet->append(file->engine->getName().c_str());
 
647
    }
 
648
 
 
649
    if (share->db_create_options & HA_OPTION_PACK_KEYS)
 
650
      packet->append(STRING_WITH_LEN(" PACK_KEYS=1"));
 
651
    if (share->db_create_options & HA_OPTION_NO_PACK_KEYS)
 
652
      packet->append(STRING_WITH_LEN(" PACK_KEYS=0"));
 
653
    if (create_info.row_type != ROW_TYPE_DEFAULT)
 
654
    {
 
655
      packet->append(STRING_WITH_LEN(" ROW_FORMAT="));
 
656
      packet->append(ha_row_type[(uint32_t) create_info.row_type]);
 
657
    }
 
658
    if (table->s->key_block_size)
 
659
    {
 
660
      packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
661
      buff= to_string(table->s->key_block_size);
 
662
      packet->append(buff.c_str(), buff.length());
 
663
    }
 
664
    if (share->block_size)
 
665
    {
 
666
      packet->append(STRING_WITH_LEN(" BLOCK_SIZE="));
 
667
      buff= to_string(share->block_size);
 
668
      packet->append(buff.c_str(), buff.length());
 
669
    }
 
670
    table->file->append_create_info(packet);
 
671
    if (share->hasComment() && share->getCommentLength())
 
672
    {
 
673
      packet->append(STRING_WITH_LEN(" COMMENT="));
 
674
      append_unescaped(packet, share->getComment(),
 
675
                       share->getCommentLength());
 
676
    }
 
677
  }
 
678
  table->restore_column_map(old_map);
 
679
  return(0);
 
680
}
 
681
 
 
682
static void store_key_options(String *packet, Table *table, KEY *key_info)
 
683
{
 
684
  char *end, buff[32];
 
685
 
 
686
  if (key_info->algorithm == HA_KEY_ALG_BTREE)
 
687
    packet->append(STRING_WITH_LEN(" USING BTREE"));
 
688
 
 
689
  if (key_info->algorithm == HA_KEY_ALG_HASH)
 
690
    packet->append(STRING_WITH_LEN(" USING HASH"));
 
691
 
 
692
  if ((key_info->flags & HA_USES_BLOCK_SIZE) &&
 
693
      table->s->key_block_size != key_info->block_size)
 
694
  {
 
695
    packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE="));
 
696
    end= int64_t10_to_str(key_info->block_size, buff, 10);
 
697
    packet->append(buff, (uint32_t) (end - buff));
 
698
  }
 
699
 
 
700
  assert(test(key_info->flags & HA_USES_COMMENT) ==
 
701
              (key_info->comment.length > 0));
 
702
  if (key_info->flags & HA_USES_COMMENT)
 
703
  {
 
704
    packet->append(STRING_WITH_LEN(" COMMENT "));
 
705
    append_unescaped(packet, key_info->comment.str,
 
706
                     key_info->comment.length);
 
707
  }
 
708
}
 
709
 
 
710
 
 
711
/****************************************************************************
 
712
  Return info about all processes
 
713
  returns for each thread: thread id, user, host, db, command, info
 
714
****************************************************************************/
 
715
 
 
716
class thread_info :public ilink {
 
717
public:
 
718
  static void *operator new(size_t size)
 
719
  {
 
720
    return (void*) sql_alloc((uint32_t) size);
 
721
  }
 
722
  static void operator delete(void *, size_t)
 
723
  { TRASH(ptr, size); }
 
724
 
 
725
  my_thread_id thread_id;
 
726
  time_t start_time;
 
727
  uint32_t   command;
 
728
  const char *user,*host,*db,*proc_info,*state_info;
 
729
  char *query;
 
730
};
 
731
 
 
732
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
733
template class I_List<thread_info>;
 
734
#endif
 
735
 
 
736
void mysqld_list_processes(Session *session,const char *user, bool)
 
737
{
 
738
  Item *field;
 
739
  List<Item> field_list;
 
740
  I_List<thread_info> thread_infos;
 
741
  plugin::Protocol *protocol= session->protocol;
 
742
 
 
743
  field_list.push_back(new Item_int("Id", 0, MY_INT32_NUM_DECIMAL_DIGITS));
 
744
  field_list.push_back(new Item_empty_string("User",16));
 
745
  field_list.push_back(new Item_empty_string("Host",LIST_PROCESS_HOST_LEN));
 
746
  field_list.push_back(field=new Item_empty_string("db",NAME_CHAR_LEN));
 
747
  field->maybe_null= true;
 
748
  field_list.push_back(new Item_empty_string("Command",16));
 
749
  field_list.push_back(new Item_return_int("Time",7, DRIZZLE_TYPE_LONG));
 
750
  field_list.push_back(field=new Item_empty_string("State",30));
 
751
  field->maybe_null= true;
 
752
  field_list.push_back(field=new Item_empty_string("Info", PROCESS_LIST_WIDTH));
 
753
  field->maybe_null= true;
 
754
  if (protocol->sendFields(&field_list))
 
755
    return;
 
756
 
 
757
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
758
  if (!session->killed)
 
759
  {
 
760
    Session *tmp;
 
761
    for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
 
762
    {
 
763
      tmp= *it;
 
764
      Security_context *tmp_sctx= &tmp->security_ctx;
 
765
      struct st_my_thread_var *mysys_var;
 
766
      if (tmp->protocol->isConnected() && (!user || (tmp_sctx->user.c_str() && !strcmp(tmp_sctx->user.c_str(), user))))
 
767
      {
 
768
        thread_info *session_info= new thread_info;
 
769
 
 
770
        session_info->thread_id=tmp->thread_id;
 
771
        session_info->user= session->strdup(tmp_sctx->user.c_str() ? tmp_sctx->user.c_str() : "unauthenticated user");
 
772
        session_info->host= session->strdup(tmp_sctx->ip.c_str());
 
773
        if ((session_info->db=tmp->db))             // Safe test
 
774
          session_info->db=session->strdup(session_info->db);
 
775
        session_info->command=(int) tmp->command;
 
776
        if ((mysys_var= tmp->mysys_var))
 
777
          pthread_mutex_lock(&mysys_var->mutex);
 
778
 
 
779
        if (tmp->killed == Session::KILL_CONNECTION)
 
780
          session_info->proc_info= (char*) "Killed";
 
781
        else
 
782
          session_info->proc_info= command_name[session_info->command].str;
 
783
 
 
784
        session_info->state_info= (char*) (tmp->protocol->isWriting() ?
 
785
                                           "Writing to net" :
 
786
                                           tmp->protocol->isReading() ?
 
787
                                           (session_info->command == COM_SLEEP ?
 
788
                                            NULL : "Reading from net") :
 
789
                                       tmp->get_proc_info() ? tmp->get_proc_info() :
 
790
                                       tmp->mysys_var &&
 
791
                                       tmp->mysys_var->current_cond ?
 
792
                                       "Waiting on cond" : NULL);
 
793
        if (mysys_var)
 
794
          pthread_mutex_unlock(&mysys_var->mutex);
 
795
 
 
796
        session_info->start_time= tmp->start_time;
 
797
        session_info->query= NULL;
 
798
        if (tmp->process_list_info[0])
 
799
          session_info->query= session->strdup(tmp->process_list_info);
 
800
        thread_infos.append(session_info);
 
801
      }
 
802
    }
 
803
  }
 
804
  pthread_mutex_unlock(&LOCK_thread_count);
 
805
 
 
806
  thread_info *session_info;
 
807
  time_t now= time(NULL);
 
808
  while ((session_info=thread_infos.get()))
 
809
  {
 
810
    protocol->prepareForResend();
 
811
    protocol->store((uint64_t) session_info->thread_id);
 
812
    protocol->store(session_info->user);
 
813
    protocol->store(session_info->host);
 
814
    protocol->store(session_info->db);
 
815
    protocol->store(session_info->proc_info);
 
816
 
 
817
    if (session_info->start_time)
 
818
      protocol->store((uint32_t) (now - session_info->start_time));
 
819
    else
 
820
      protocol->store();
 
821
 
 
822
    protocol->store(session_info->state_info);
 
823
    protocol->store(session_info->query);
 
824
 
 
825
    if (protocol->write())
 
826
      break; /* purecov: inspected */
 
827
  }
 
828
  session->my_eof();
 
829
  return;
 
830
}
 
831
 
 
832
/*****************************************************************************
 
833
  Status functions
 
834
*****************************************************************************/
 
835
 
 
836
static vector<SHOW_VAR *> all_status_vars;
 
837
static bool status_vars_inited= 0;
 
838
int show_var_cmp(const void *var1, const void *var2)
 
839
{
 
840
  return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
 
841
}
 
842
 
 
843
class show_var_cmp_functor
 
844
{
 
845
  public:
 
846
  show_var_cmp_functor() { }
 
847
  inline bool operator()(const SHOW_VAR *var1, const SHOW_VAR *var2) const
 
848
  {
 
849
    int val= strcmp(var1->name, var2->name);
 
850
    return (val < 0);
 
851
  }
 
852
};
 
853
 
 
854
class show_var_remove_if
 
855
{
 
856
  public:
 
857
  show_var_remove_if() { }
 
858
  inline bool operator()(const SHOW_VAR *curr) const
 
859
  {
 
860
    return (curr->type == SHOW_UNDEF);
 
861
  }
 
862
};
 
863
 
 
864
SHOW_VAR *getFrontOfStatusVars()
 
865
{
 
866
  return all_status_vars.front();
 
867
}
 
868
 
 
869
/*
 
870
  Adds an array of SHOW_VAR entries to the output of SHOW STATUS
 
871
 
 
872
  SYNOPSIS
 
873
    add_status_vars(SHOW_VAR *list)
 
874
    list - an array of SHOW_VAR entries to add to all_status_vars
 
875
           the last entry must be {0,0,SHOW_UNDEF}
 
876
 
 
877
  NOTE
 
878
    The handling of all_status_vars[] is completely internal, it's allocated
 
879
    automatically when something is added to it, and deleted completely when
 
880
    the last entry is removed.
 
881
 
 
882
    As a special optimization, if add_status_vars() is called before
 
883
    init_status_vars(), it assumes "startup mode" - neither concurrent access
 
884
    to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
 
885
*/
 
886
int add_status_vars(SHOW_VAR *list)
 
887
{
 
888
  int res= 0;
 
889
  if (status_vars_inited)
 
890
    pthread_mutex_lock(&LOCK_status);
 
891
  while (list->name)
 
892
    all_status_vars.insert(all_status_vars.begin(), list++);
 
893
  if (status_vars_inited)
 
894
    sort(all_status_vars.begin(), all_status_vars.end(),
 
895
         show_var_cmp_functor());
 
896
  if (status_vars_inited)
 
897
    pthread_mutex_unlock(&LOCK_status);
 
898
  return res;
 
899
}
 
900
 
 
901
/*
 
902
  Make all_status_vars[] usable for SHOW STATUS
 
903
 
 
904
  NOTE
 
905
    See add_status_vars(). Before init_status_vars() call, add_status_vars()
 
906
    works in a special fast "startup" mode. Thus init_status_vars()
 
907
    should be called as late as possible but before enabling multi-threading.
 
908
*/
 
909
void init_status_vars()
 
910
{
 
911
  status_vars_inited= 1;
 
912
  sort(all_status_vars.begin(), all_status_vars.end(),
 
913
       show_var_cmp_functor());
 
914
}
 
915
 
 
916
void reset_status_vars()
 
917
{
 
918
  vector<SHOW_VAR *>::iterator p= all_status_vars.begin();
 
919
  while (p != all_status_vars.end())
 
920
  {
 
921
    /* Note that SHOW_LONG_NOFLUSH variables are not reset */
 
922
    if ((*p)->type == SHOW_LONG)
 
923
      (*p)->value= 0;
 
924
    ++p;
 
925
  }
 
926
}
 
927
 
 
928
/*
 
929
  catch-all cleanup function, cleans up everything no matter what
 
930
 
 
931
  DESCRIPTION
 
932
    This function is not strictly required if all add_to_status/
 
933
    remove_status_vars are properly paired, but it's a safety measure that
 
934
    deletes everything from the all_status_vars vector even if some
 
935
    remove_status_vars were forgotten
 
936
*/
 
937
void free_status_vars()
 
938
{
 
939
  all_status_vars.clear();
 
940
}
 
941
 
 
942
/*
 
943
  Removes an array of SHOW_VAR entries from the output of SHOW STATUS
 
944
 
 
945
  SYNOPSIS
 
946
    remove_status_vars(SHOW_VAR *list)
 
947
    list - an array of SHOW_VAR entries to remove to all_status_vars
 
948
           the last entry must be {0,0,SHOW_UNDEF}
 
949
 
 
950
  NOTE
 
951
    there's lots of room for optimizing this, especially in non-sorted mode,
 
952
    but nobody cares - it may be called only in case of failed plugin
 
953
    initialization in the mysqld startup.
 
954
*/
 
955
 
 
956
void remove_status_vars(SHOW_VAR *list)
 
957
{
 
958
  if (status_vars_inited)
 
959
  {
 
960
    pthread_mutex_lock(&LOCK_status);
 
961
    SHOW_VAR *all= all_status_vars.front();
 
962
    int a= 0, b= all_status_vars.size(), c= (a+b)/2;
 
963
 
 
964
    for (; list->name; list++)
 
965
    {
 
966
      int res= 0;
 
967
      for (a= 0, b= all_status_vars.size(); b-a > 1; c= (a+b)/2)
 
968
      {
 
969
        res= show_var_cmp(list, all+c);
 
970
        if (res < 0)
 
971
          b= c;
 
972
        else if (res > 0)
 
973
          a= c;
 
974
        else
 
975
          break;
 
976
      }
 
977
      if (res == 0)
 
978
        all[c].type= SHOW_UNDEF;
 
979
    }
 
980
    /* removes all the SHOW_UNDEF elements from the vector */
 
981
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
982
                            all_status_vars.end(),show_var_remove_if()),
 
983
                            all_status_vars.end());
 
984
    pthread_mutex_unlock(&LOCK_status);
 
985
  }
 
986
  else
 
987
  {
 
988
    SHOW_VAR *all= all_status_vars.front();
 
989
    uint32_t i;
 
990
    for (; list->name; list++)
 
991
    {
 
992
      for (i= 0; i < all_status_vars.size(); i++)
 
993
      {
 
994
        if (show_var_cmp(list, all+i))
 
995
          continue;
 
996
        all[i].type= SHOW_UNDEF;
 
997
        break;
 
998
      }
 
999
    }
 
1000
    /* removes all the SHOW_UNDEF elements from the vector */
 
1001
    all_status_vars.erase(std::remove_if(all_status_vars.begin(),
 
1002
                            all_status_vars.end(),show_var_remove_if()),
 
1003
                            all_status_vars.end());
 
1004
  }
 
1005
}
 
1006
 
 
1007
/* collect status for all running threads */
 
1008
 
 
1009
void calc_sum_of_all_status(STATUS_VAR *to)
 
1010
{
 
1011
  /* Ensure that thread id not killed during loop */
 
1012
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
1013
 
 
1014
  /* Get global values as base */
 
1015
  *to= global_status_var;
 
1016
 
 
1017
  /* Add to this status from existing threads */
 
1018
  for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
 
1019
  {
 
1020
    add_to_status(to, &((*it)->status_var));
 
1021
  }
 
1022
 
 
1023
  pthread_mutex_unlock(&LOCK_thread_count);
 
1024
  return;
 
1025
}
 
1026
 
 
1027
/*
 
1028
  Store record to I_S table, convert HEAP table
 
1029
  to MyISAM if necessary
 
1030
 
 
1031
  SYNOPSIS
 
1032
    schema_table_store_record()
 
1033
    session                   thread handler
 
1034
    table                 Information schema table to be updated
 
1035
 
 
1036
  RETURN
 
1037
    0                     success
 
1038
    1                     error
 
1039
*/
 
1040
 
 
1041
bool schema_table_store_record(Session *session, Table *table)
 
1042
{
 
1043
  int error;
 
1044
  if ((error= table->file->ha_write_row(table->record[0])))
 
1045
  {
 
1046
    Tmp_Table_Param *param= table->pos_in_table_list->schema_table_param;
 
1047
 
 
1048
    if (create_myisam_from_heap(session, table, param->start_recinfo,
 
1049
                                &param->recinfo, error, 0))
 
1050
      return true;
 
1051
  }
 
1052
  return false;
 
1053
}
 
1054
 
 
1055
 
 
1056
static int make_table_list(Session *session, Select_Lex *sel,
 
1057
                           LEX_STRING *db_name, LEX_STRING *table_name)
 
1058
{
 
1059
  Table_ident *table_ident;
 
1060
  table_ident= new Table_ident(*db_name, *table_name);
 
1061
  sel->init_query();
 
1062
  if (! sel->add_table_to_list(session, table_ident, 0, 0, TL_READ))
 
1063
    return 1;
 
1064
  return 0;
 
1065
}
 
1066
 
 
1067
 
 
1068
/**
 
1069
  @brief    Get lookup value from the part of 'WHERE' condition
 
1070
 
 
1071
  @details This function gets lookup value from
 
1072
           the part of 'WHERE' condition if it's possible and
 
1073
           fill appropriate lookup_field_vals struct field
 
1074
           with this value.
 
1075
 
 
1076
  @param[in]      session                   thread handler
 
1077
  @param[in]      item_func             part of WHERE condition
 
1078
  @param[in]      table                 I_S table
 
1079
  @param[in, out] lookup_field_vals     Struct which holds lookup values
 
1080
 
 
1081
  @return
 
1082
    0             success
 
1083
    1             error, there can be no matching records for the condition
 
1084
*/
 
1085
 
 
1086
static bool get_lookup_value(Session *session, Item_func *item_func,
 
1087
                             TableList *table,
 
1088
                             LOOKUP_FIELD_VALUES *lookup_field_vals)
 
1089
{
 
1090
  plugin::InfoSchema *schema_table= table->schema_table;
 
1091
  const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
 
1092
    schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
 
1093
  const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
 
1094
    schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
 
1095
 
 
1096
  if (item_func->functype() == Item_func::EQ_FUNC ||
 
1097
      item_func->functype() == Item_func::EQUAL_FUNC)
 
1098
  {
 
1099
    int idx_field, idx_val;
 
1100
    char tmp[MAX_FIELD_WIDTH];
 
1101
    String *tmp_str, str_buff(tmp, sizeof(tmp), system_charset_info);
 
1102
    Item_field *item_field;
 
1103
    const CHARSET_INFO * const cs= system_charset_info;
 
1104
 
 
1105
    if (item_func->arguments()[0]->type() == Item::FIELD_ITEM &&
 
1106
        item_func->arguments()[1]->const_item())
 
1107
    {
 
1108
      idx_field= 0;
 
1109
      idx_val= 1;
 
1110
    }
 
1111
    else if (item_func->arguments()[1]->type() == Item::FIELD_ITEM &&
 
1112
             item_func->arguments()[0]->const_item())
 
1113
    {
 
1114
      idx_field= 1;
 
1115
      idx_val= 0;
 
1116
    }
 
1117
    else
 
1118
      return 0;
 
1119
 
 
1120
    item_field= (Item_field*) item_func->arguments()[idx_field];
 
1121
    if (table->table != item_field->field->table)
 
1122
      return 0;
 
1123
    tmp_str= item_func->arguments()[idx_val]->val_str(&str_buff);
 
1124
 
 
1125
    /* impossible value */
 
1126
    if (!tmp_str)
 
1127
      return 1;
 
1128
 
 
1129
    /* Lookup value is database name */
 
1130
    if (!cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
 
1131
                               (unsigned char *) item_field->field_name,
 
1132
                               strlen(item_field->field_name), 0))
 
1133
    {
 
1134
      session->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(),
 
1135
                           tmp_str->length(), false);
 
1136
    }
 
1137
    /* Lookup value is table name */
 
1138
    else if (!cs->coll->strnncollsp(cs, (unsigned char *) field_name2,
 
1139
                                    strlen(field_name2),
 
1140
                                    (unsigned char *) item_field->field_name,
 
1141
                                    strlen(item_field->field_name), 0))
 
1142
    {
 
1143
      session->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(),
 
1144
                           tmp_str->length(), false);
 
1145
    }
 
1146
  }
 
1147
  return 0;
 
1148
}
 
1149
 
 
1150
 
 
1151
/**
 
1152
  @brief    Calculates lookup values from 'WHERE' condition
 
1153
 
 
1154
  @details This function calculates lookup value(database name, table name)
 
1155
           from 'WHERE' condition if it's possible and
 
1156
           fill lookup_field_vals struct fields with these values.
 
1157
 
 
1158
  @param[in]      session                   thread handler
 
1159
  @param[in]      cond                  WHERE condition
 
1160
  @param[in]      table                 I_S table
 
1161
  @param[in, out] lookup_field_vals     Struct which holds lookup values
 
1162
 
 
1163
  @return
 
1164
    0             success
 
1165
    1             error, there can be no matching records for the condition
 
1166
*/
 
1167
 
 
1168
bool calc_lookup_values_from_cond(Session *session, COND *cond, TableList *table,
 
1169
                                  LOOKUP_FIELD_VALUES *lookup_field_vals)
 
1170
{
 
1171
  if (!cond)
 
1172
    return 0;
 
1173
 
 
1174
  if (cond->type() == Item::COND_ITEM)
 
1175
  {
 
1176
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
 
1177
    {
 
1178
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
1179
      Item *item;
 
1180
      while ((item= li++))
 
1181
      {
 
1182
        if (item->type() == Item::FUNC_ITEM)
 
1183
        {
 
1184
          if (get_lookup_value(session, (Item_func*)item, table, lookup_field_vals))
 
1185
            return 1;
 
1186
        }
 
1187
        else
 
1188
        {
 
1189
          if (calc_lookup_values_from_cond(session, item, table, lookup_field_vals))
 
1190
            return 1;
 
1191
        }
 
1192
      }
 
1193
    }
 
1194
    return 0;
 
1195
  }
 
1196
  else if (cond->type() == Item::FUNC_ITEM &&
 
1197
           get_lookup_value(session, (Item_func*) cond, table, lookup_field_vals))
 
1198
    return 1;
 
1199
  return 0;
 
1200
}
 
1201
 
 
1202
 
 
1203
static bool uses_only_table_name_fields(Item *item, TableList *table)
 
1204
{
 
1205
  if (item->type() == Item::FUNC_ITEM)
 
1206
  {
 
1207
    Item_func *item_func= (Item_func*)item;
 
1208
    for (uint32_t i=0; i<item_func->argument_count(); i++)
 
1209
    {
 
1210
      if (!uses_only_table_name_fields(item_func->arguments()[i], table))
 
1211
        return 0;
 
1212
    }
 
1213
  }
 
1214
  else if (item->type() == Item::FIELD_ITEM)
 
1215
  {
 
1216
    Item_field *item_field= (Item_field*)item;
 
1217
    const CHARSET_INFO * const cs= system_charset_info;
 
1218
    plugin::InfoSchema *schema_table= table->schema_table;
 
1219
    const char *field_name1= schema_table->getFirstColumnIndex() >= 0 ?
 
1220
      schema_table->getColumnName(schema_table->getFirstColumnIndex()).c_str() : "";
 
1221
    const char *field_name2= schema_table->getSecondColumnIndex() >= 0 ?
 
1222
      schema_table->getColumnName(schema_table->getSecondColumnIndex()).c_str() : "";
 
1223
    if (table->table != item_field->field->table ||
 
1224
        (cs->coll->strnncollsp(cs, (unsigned char *) field_name1, strlen(field_name1),
 
1225
                               (unsigned char *) item_field->field_name,
 
1226
                               strlen(item_field->field_name), 0) &&
 
1227
         cs->coll->strnncollsp(cs, (unsigned char *) field_name2, strlen(field_name2),
 
1228
                               (unsigned char *) item_field->field_name,
 
1229
                               strlen(item_field->field_name), 0)))
 
1230
      return 0;
 
1231
  }
 
1232
  else if (item->type() == Item::REF_ITEM)
 
1233
    return uses_only_table_name_fields(item->real_item(), table);
 
1234
 
 
1235
  if (item->type() == Item::SUBSELECT_ITEM && !item->const_item())
 
1236
    return 0;
 
1237
 
 
1238
  return 1;
 
1239
}
 
1240
 
 
1241
 
 
1242
static COND * make_cond_for_info_schema(COND *cond, TableList *table)
 
1243
{
 
1244
  if (!cond)
 
1245
    return (COND*) 0;
 
1246
  if (cond->type() == Item::COND_ITEM)
 
1247
  {
 
1248
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
 
1249
    {
 
1250
      /* Create new top level AND item */
 
1251
      Item_cond_and *new_cond=new Item_cond_and;
 
1252
      if (!new_cond)
 
1253
        return (COND*) 0;
 
1254
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
1255
      Item *item;
 
1256
      while ((item=li++))
 
1257
      {
 
1258
        Item *fix= make_cond_for_info_schema(item, table);
 
1259
        if (fix)
 
1260
          new_cond->argument_list()->push_back(fix);
 
1261
      }
 
1262
      switch (new_cond->argument_list()->elements) {
 
1263
      case 0:
 
1264
        return (COND*) 0;
 
1265
      case 1:
 
1266
        return new_cond->argument_list()->head();
 
1267
      default:
 
1268
        new_cond->quick_fix_field();
 
1269
        return new_cond;
 
1270
      }
 
1271
    }
 
1272
    else
 
1273
    {                                           // Or list
 
1274
      Item_cond_or *new_cond=new Item_cond_or;
 
1275
      if (!new_cond)
 
1276
        return (COND*) 0;
 
1277
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
 
1278
      Item *item;
 
1279
      while ((item=li++))
 
1280
      {
 
1281
        Item *fix=make_cond_for_info_schema(item, table);
 
1282
        if (!fix)
 
1283
          return (COND*) 0;
 
1284
        new_cond->argument_list()->push_back(fix);
 
1285
      }
 
1286
      new_cond->quick_fix_field();
 
1287
      new_cond->top_level_item();
 
1288
      return new_cond;
 
1289
    }
 
1290
  }
 
1291
 
 
1292
  if (!uses_only_table_name_fields(cond, table))
 
1293
    return (COND*) 0;
 
1294
  return cond;
 
1295
}
 
1296
 
 
1297
 
 
1298
/**
 
1299
  @brief   Calculate lookup values(database name, table name)
 
1300
 
 
1301
  @details This function calculates lookup values(database name, table name)
 
1302
           from 'WHERE' condition or wild values (for 'SHOW' commands only)
 
1303
           from LEX struct and fill lookup_field_vals struct field
 
1304
           with these values.
 
1305
 
 
1306
  @param[in]      session                   thread handler
 
1307
  @param[in]      cond                  WHERE condition
 
1308
  @param[in]      tables                I_S table
 
1309
  @param[in, out] lookup_field_values   Struct which holds lookup values
 
1310
 
 
1311
  @return
 
1312
    0             success
 
1313
    1             error, there can be no matching records for the condition
 
1314
*/
 
1315
 
 
1316
bool get_lookup_field_values(Session *session, COND *cond, TableList *tables,
 
1317
                             LOOKUP_FIELD_VALUES *lookup_field_values)
 
1318
{
 
1319
  LEX *lex= session->lex;
 
1320
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
 
1321
  memset(lookup_field_values, 0, sizeof(LOOKUP_FIELD_VALUES));
 
1322
  switch (lex->sql_command) {
 
1323
  case SQLCOM_SHOW_DATABASES:
 
1324
    if (wild)
 
1325
    {
 
1326
      lookup_field_values->db_value.str= (char*) wild;
 
1327
      lookup_field_values->db_value.length= strlen(wild);
 
1328
      lookup_field_values->wild_db_value= 1;
 
1329
    }
 
1330
    return 0;
 
1331
  case SQLCOM_SHOW_TABLES:
 
1332
  case SQLCOM_SHOW_TABLE_STATUS:
 
1333
    lookup_field_values->db_value.str= lex->select_lex.db;
 
1334
    lookup_field_values->db_value.length=strlen(lex->select_lex.db);
 
1335
    if (wild)
 
1336
    {
 
1337
      lookup_field_values->table_value.str= (char*)wild;
 
1338
      lookup_field_values->table_value.length= strlen(wild);
 
1339
      lookup_field_values->wild_table_value= 1;
 
1340
    }
 
1341
    return 0;
 
1342
  default:
 
1343
    /*
 
1344
      The "default" is for queries over I_S.
 
1345
      All previous cases handle SHOW commands.
 
1346
    */
 
1347
    return calc_lookup_values_from_cond(session, cond, tables, lookup_field_values);
 
1348
  }
 
1349
}
 
1350
 
 
1351
 
 
1352
/**
 
1353
 * Function used for sorting with std::sort within make_db_list.
 
1354
 *
 
1355
 * @returns true if a < b, false otherwise
 
1356
 */
 
1357
 
 
1358
static bool lex_string_sort(const LEX_STRING *a, const LEX_STRING *b)
 
1359
{
 
1360
  return (strcmp(a->str, b->str) < 0);
 
1361
}
 
1362
 
 
1363
 
 
1364
/**
 
1365
 * @brief
 
1366
 *   Create db names list. Information schema name always is first in list
 
1367
 *
 
1368
 * @param[in]  session          Thread handler
 
1369
 * @param[out] files            List of db names
 
1370
 * @param[in]  wild             Wild string
 
1371
 * @param[in]  idx_field_vals   idx_field_vals->db_name contains db name or
 
1372
 *                              wild string
 
1373
 * @param[out] with_i_schema    Returns 1 if we added 'IS' name to list
 
1374
 *                              otherwise returns 0
 
1375
 *
 
1376
 * @retval 0   Success
 
1377
 * @retval 1   Error
 
1378
 */
 
1379
int make_db_list(Session *session, vector<LEX_STRING*> &files,
 
1380
                 LOOKUP_FIELD_VALUES *lookup_field_vals,
 
1381
                 bool *with_i_schema)
 
1382
{
 
1383
  LEX_STRING *i_s_name_copy= 0;
 
1384
  i_s_name_copy= session->make_lex_string(i_s_name_copy,
 
1385
                                      INFORMATION_SCHEMA_NAME.c_str(),
 
1386
                                      INFORMATION_SCHEMA_NAME.length(), true);
 
1387
  *with_i_schema= 0;
 
1388
  if (lookup_field_vals->wild_db_value)
 
1389
  {
 
1390
    /*
 
1391
      This part of code is only for SHOW DATABASES command.
 
1392
      idx_field_vals->db_value can be 0 when we don't use
 
1393
      LIKE clause (see also get_index_field_values() function)
 
1394
    */
 
1395
    if (!lookup_field_vals->db_value.str ||
 
1396
        !wild_case_compare(system_charset_info,
 
1397
                           INFORMATION_SCHEMA_NAME.c_str(),
 
1398
                           lookup_field_vals->db_value.str))
 
1399
    {
 
1400
      *with_i_schema= 1;
 
1401
      files.push_back(i_s_name_copy);
 
1402
    }
 
1403
 
 
1404
    if (find_schemas(session, files, drizzle_data_home,
 
1405
                     lookup_field_vals->db_value.str) == true)
 
1406
    {
 
1407
      return 1;
 
1408
    }
 
1409
 
 
1410
    sort(files.begin()+1, files.end(), lex_string_sort);
 
1411
    return 0;
 
1412
  }
 
1413
 
 
1414
 
 
1415
  /*
 
1416
    If we have db lookup vaule we just add it to list and
 
1417
    exit from the function
 
1418
  */
 
1419
  if (lookup_field_vals->db_value.str)
 
1420
  {
 
1421
    if (!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.c_str(),
 
1422
                       lookup_field_vals->db_value.str))
 
1423
    {
 
1424
      *with_i_schema= 1;
 
1425
      files.push_back(i_s_name_copy);
 
1426
      return 0;
 
1427
    }
 
1428
 
 
1429
    files.push_back(&lookup_field_vals->db_value);
 
1430
    return 0;
 
1431
  }
 
1432
 
 
1433
  /*
 
1434
    Create list of existing databases. It is used in case
 
1435
    of select from information schema table
 
1436
  */
 
1437
  files.push_back(i_s_name_copy);
 
1438
 
 
1439
  *with_i_schema= 1;
 
1440
 
 
1441
  if (find_schemas(session, files, drizzle_data_home, NULL) == true)
 
1442
  {
 
1443
    return 1;
 
1444
  }
 
1445
 
 
1446
  sort(files.begin()+1, files.end(), lex_string_sort);
 
1447
  return 0;
 
1448
}
 
1449
 
 
1450
 
 
1451
 
 
1452
 
 
1453
static int schema_tables_add(Session *session,
 
1454
                             vector<LEX_STRING*> &files,
 
1455
                             const char *wild)
 
1456
{
 
1457
  plugin::Registry &plugins= plugin::Registry::singleton();
 
1458
  return plugins.info_schema.addTableToList(session, files, wild);
 
1459
}
 
1460
 
 
1461
 
 
1462
/**
 
1463
  @brief          Create table names list
 
1464
 
 
1465
  @details        The function creates the list of table names in
 
1466
                  database
 
1467
 
 
1468
  @param[in]      session                   thread handler
 
1469
  @param[in]      table_names           List of table names in database
 
1470
  @param[in]      lex                   pointer to LEX struct
 
1471
  @param[in]      lookup_field_vals     pointer to LOOKUP_FIELD_VALUE struct
 
1472
  @param[in]      with_i_schema         true means that we add I_S tables to list
 
1473
  @param[in]      db_name               database name
 
1474
 
 
1475
  @return         Operation status
 
1476
    @retval       0           ok
 
1477
    @retval       1           fatal error
 
1478
    @retval       2           Not fatal error; Safe to ignore this file list
 
1479
*/
 
1480
 
 
1481
static int
 
1482
make_table_name_list(Session *session, vector<LEX_STRING*> &table_names, LEX *lex,
 
1483
                     LOOKUP_FIELD_VALUES *lookup_field_vals,
 
1484
                     bool with_i_schema, LEX_STRING *db_name)
 
1485
{
 
1486
  char path[FN_REFLEN];
 
1487
  build_table_filename(path, sizeof(path), db_name->str, "", false);
 
1488
  if (!lookup_field_vals->wild_table_value &&
 
1489
      lookup_field_vals->table_value.str)
 
1490
  {
 
1491
    if (with_i_schema)
 
1492
    {
 
1493
      if (find_schema_table(lookup_field_vals->table_value.str))
 
1494
      {
 
1495
        table_names.push_back(&lookup_field_vals->table_value);
 
1496
      }
 
1497
    }
 
1498
    else
 
1499
    {
 
1500
      table_names.push_back(&lookup_field_vals->table_value);
 
1501
    }
 
1502
    return 0;
 
1503
  }
 
1504
 
 
1505
  /*
 
1506
    This call will add all matching the wildcards (if specified) IS tables
 
1507
    to the list
 
1508
  */
 
1509
  if (with_i_schema)
 
1510
    return (schema_tables_add(session, table_names,
 
1511
                              lookup_field_vals->table_value.str));
 
1512
 
 
1513
  string db(db_name->str);
 
1514
 
 
1515
  TableNameIterator tniter(db);
 
1516
  int err= 0;
 
1517
  string table_name;
 
1518
 
 
1519
  do {
 
1520
    err= tniter.next(&table_name);
 
1521
 
 
1522
    if (err == 0)
 
1523
    {
 
1524
      LEX_STRING *file_name= NULL;
 
1525
      file_name= session->make_lex_string(file_name, table_name.c_str(),
 
1526
                                          table_name.length(), true);
 
1527
      const char* wild= lookup_field_vals->table_value.str;
 
1528
      if (wild && wild_compare(table_name.c_str(), wild, 0))
 
1529
        continue;
 
1530
      table_names.push_back(file_name);
 
1531
    }
 
1532
 
 
1533
  } while (err == 0);
 
1534
 
 
1535
  if (err > 0)
 
1536
  {
 
1537
    /* who knows what this error condition really does...
 
1538
       anyway, we're keeping behaviour from days of yore */
 
1539
    if (lex->sql_command != SQLCOM_SELECT)
 
1540
      return 1;
 
1541
    session->clear_error();
 
1542
    return 2;
 
1543
  }
 
1544
 
 
1545
  return 0;
 
1546
}
 
1547
 
 
1548
 
 
1549
/**
 
1550
  @brief          Fill I_S table for SHOW COLUMNS|INDEX commands
 
1551
 
 
1552
  @param[in]      session                      thread handler
 
1553
  @param[in]      tables                   TableList for I_S table
 
1554
  @param[in]      schema_table             pointer to I_S structure
 
1555
  @param[in]      open_tables_state_backup pointer to Open_tables_state object
 
1556
                                           which is used to save|restore original
 
1557
                                           status of variables related to
 
1558
                                           open tables state
 
1559
 
 
1560
  @return         Operation status
 
1561
    @retval       0           success
 
1562
    @retval       1           error
 
1563
*/
 
1564
 
 
1565
static int
 
1566
fill_schema_show_cols_or_idxs(Session *session, TableList *tables,
 
1567
                              plugin::InfoSchema *schema_table,
 
1568
                              Open_tables_state *open_tables_state_backup)
 
1569
{
 
1570
  LEX *lex= session->lex;
 
1571
  bool res;
 
1572
  LEX_STRING tmp_lex_string, tmp_lex_string1, *db_name, *table_name;
 
1573
  enum_sql_command save_sql_command= lex->sql_command;
 
1574
  TableList *show_table_list= (TableList*) tables->schema_select_lex->
 
1575
    table_list.first;
 
1576
  Table *table= tables->table;
 
1577
  int error= 1;
 
1578
 
 
1579
  lex->all_selects_list= tables->schema_select_lex;
 
1580
  /*
 
1581
    Restore session->temporary_tables to be able to process
 
1582
    temporary tables(only for 'show index' & 'show columns').
 
1583
    This should be changed when processing of temporary tables for
 
1584
    I_S tables will be done.
 
1585
  */
 
1586
  session->temporary_tables= open_tables_state_backup->temporary_tables;
 
1587
  /*
 
1588
    Let us set fake sql_command so views won't try to merge
 
1589
    themselves into main statement. If we don't do this,
 
1590
    SELECT * from information_schema.xxxx will cause problems.
 
1591
    SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
 
1592
  */
 
1593
  lex->sql_command= SQLCOM_SHOW_FIELDS;
 
1594
  res= session->openTables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
 
1595
  lex->sql_command= save_sql_command;
 
1596
  /*
 
1597
    get_all_tables() returns 1 on failure and 0 on success thus
 
1598
    return only these and not the result code of ::process_table()
 
1599
 
 
1600
    We should use show_table_list->alias instead of
 
1601
    show_table_list->table_name because table_name
 
1602
    could be changed during opening of I_S tables. It's safe
 
1603
    to use alias because alias contains original table name
 
1604
    in this case(this part of code is used only for
 
1605
    'show columns' & 'show statistics' commands).
 
1606
  */
 
1607
   table_name= session->make_lex_string(&tmp_lex_string1, show_table_list->alias,
 
1608
                                    strlen(show_table_list->alias), false);
 
1609
   db_name= session->make_lex_string(&tmp_lex_string, show_table_list->db,
 
1610
                                 show_table_list->db_length, false);
 
1611
 
 
1612
 
 
1613
   table->setWriteSet();
 
1614
   error= test(schema_table->processTable(session, show_table_list,
 
1615
                                          table, res, db_name,
 
1616
                                          table_name));
 
1617
   session->temporary_tables= 0;
 
1618
   session->close_tables_for_reopen(&show_table_list);
 
1619
 
 
1620
   return(error);
 
1621
}
 
1622
 
 
1623
 
 
1624
/**
 
1625
  @brief          Fill I_S table for SHOW Table NAMES commands
 
1626
 
 
1627
  @param[in]      session                      thread handler
 
1628
  @param[in]      table                    Table struct for I_S table
 
1629
  @param[in]      db_name                  database name
 
1630
  @param[in]      table_name               table name
 
1631
  @param[in]      with_i_schema            I_S table if true
 
1632
 
 
1633
  @return         Operation status
 
1634
    @retval       0           success
 
1635
    @retval       1           error
 
1636
*/
 
1637
 
 
1638
static int fill_schema_table_names(Session *session, Table *table,
 
1639
                                   LEX_STRING *db_name, LEX_STRING *table_name,
 
1640
                                   bool with_i_schema)
 
1641
{
 
1642
  if (with_i_schema)
 
1643
  {
 
1644
    table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"),
 
1645
                           system_charset_info);
 
1646
  }
 
1647
  else
 
1648
  {
 
1649
    char path[FN_REFLEN];
 
1650
    (void) build_table_filename(path, sizeof(path), db_name->str,
 
1651
                                table_name->str, false);
 
1652
 
 
1653
      table->field[3]->store(STRING_WITH_LEN("BASE Table"),
 
1654
                             system_charset_info);
 
1655
 
 
1656
    if (session->is_error() && session->main_da.sql_errno() == ER_NO_SUCH_TABLE)
 
1657
    {
 
1658
      session->clear_error();
 
1659
      return 0;
 
1660
    }
 
1661
  }
 
1662
  if (schema_table_store_record(session, table))
 
1663
    return 1;
 
1664
  return 0;
 
1665
}
 
1666
 
 
1667
 
 
1668
/**
 
1669
  @brief          Get open table method
 
1670
 
 
1671
  @details        The function calculates the method which will be used
 
1672
                  for table opening:
 
1673
                  SKIP_OPEN_TABLE - do not open table
 
1674
                  OPEN_FRM_ONLY   - open FRM file only
 
1675
                  OPEN_FULL_TABLE - open FRM, data, index files
 
1676
  @param[in]      tables               I_S table table_list
 
1677
  @param[in]      schema_table         I_S table struct
 
1678
 
 
1679
  @return         return a set of flags
 
1680
    @retval       SKIP_OPEN_TABLE | OPEN_FRM_ONLY | OPEN_FULL_TABLE
 
1681
*/
 
1682
 
 
1683
static uint32_t get_table_open_method(TableList *tables,
 
1684
                                      plugin::InfoSchema *schema_table)
 
1685
{
 
1686
  /*
 
1687
    determine which method will be used for table opening
 
1688
  */
 
1689
  if (schema_table->getRequestedObject() & OPTIMIZE_I_S_TABLE)
 
1690
  {
 
1691
    Field **ptr, *field;
 
1692
    int table_open_method= 0, field_indx= 0;
 
1693
    for (ptr= tables->table->field; (field= *ptr) ; ptr++)
 
1694
    {
 
1695
      if (field->isReadSet())
 
1696
        table_open_method|= schema_table->getColumnOpenMethod(field_indx);
 
1697
      field_indx++;
 
1698
    }
 
1699
    return table_open_method;
 
1700
  }
 
1701
  /* I_S tables which use get_all_tables but can not be optimized */
 
1702
  return (uint32_t) OPEN_FULL_TABLE;
 
1703
}
 
1704
 
 
1705
 
 
1706
/**
 
1707
  @brief          Fill I_S table with data from FRM file only
 
1708
 
 
1709
  @param[in]      session                      thread handler
 
1710
  @param[in]      table                    Table struct for I_S table
 
1711
  @param[in]      schema_table             I_S table struct
 
1712
  @param[in]      db_name                  database name
 
1713
  @param[in]      table_name               table name
 
1714
 
 
1715
  @return         Operation status
 
1716
    @retval       0           Table is processed and we can continue
 
1717
                              with new table
 
1718
    @retval       1           It's view and we have to use
 
1719
                              open_tables function for this table
 
1720
*/
 
1721
 
 
1722
static int fill_schema_table_from_frm(Session *session,TableList *tables,
 
1723
                                      plugin::InfoSchema *schema_table,
 
1724
                                      LEX_STRING *db_name,
 
1725
                                      LEX_STRING *table_name)
 
1726
{
 
1727
  Table *table= tables->table;
 
1728
  TableShare *share;
 
1729
  Table tbl;
 
1730
  TableList table_list;
 
1731
  uint32_t res= 0;
 
1732
  int error;
 
1733
  char key[MAX_DBKEY_LENGTH];
 
1734
  uint32_t key_length;
 
1735
 
 
1736
  memset(&tbl, 0, sizeof(Table));
 
1737
 
 
1738
  table_list.table_name= table_name->str;
 
1739
  table_list.db= db_name->str;
 
1740
 
 
1741
  key_length= table_list.create_table_def_key(key);
 
1742
  pthread_mutex_lock(&LOCK_open); /* Locking to get table share when filling schema table from FRM */
 
1743
  share= TableShare::getShare(session, &table_list, key, key_length, 0, &error);
 
1744
  if (!share)
 
1745
  {
 
1746
    res= 0;
 
1747
    goto err;
 
1748
  }
 
1749
 
 
1750
  {
 
1751
    tbl.s= share;
 
1752
    table_list.table= &tbl;
 
1753
    res= schema_table->processTable(session, &table_list, table,
 
1754
                                    res, db_name, table_name);
 
1755
  }
 
1756
  /* For the moment we just set everything to read */
 
1757
  table->setReadSet();
 
1758
 
 
1759
  TableShare::release(share);
 
1760
 
 
1761
err:
 
1762
  pthread_mutex_unlock(&LOCK_open);
 
1763
  session->clear_error();
 
1764
  return res;
 
1765
}
 
1766
 
 
1767
 
 
1768
 
 
1769
/**
 
1770
  @brief          Fill I_S tables whose data are retrieved
 
1771
                  from frm files and storage engine
 
1772
 
 
1773
  @details        The information schema tables are internally represented as
 
1774
                  temporary tables that are filled at query execution time.
 
1775
                  Those I_S tables whose data are retrieved
 
1776
                  from frm files and storage engine are filled by the function
 
1777
                  plugin::InfoSchemaMethods::fillTable().
 
1778
 
 
1779
  @param[in]      session                      thread handler
 
1780
  @param[in]      tables                   I_S table
 
1781
  @param[in]      cond                     'WHERE' condition
 
1782
 
 
1783
  @return         Operation status
 
1784
    @retval       0                        success
 
1785
    @retval       1                        error
 
1786
*/
 
1787
int plugin::InfoSchemaMethods::fillTable(Session *session, TableList *tables, COND *cond)
 
1788
{
 
1789
  LEX *lex= session->lex;
 
1790
  Table *table= tables->table;
 
1791
  Select_Lex *old_all_select_lex= lex->all_selects_list;
 
1792
  enum_sql_command save_sql_command= lex->sql_command;
 
1793
  Select_Lex *lsel= tables->schema_select_lex;
 
1794
  plugin::InfoSchema *schema_table= tables->schema_table;
 
1795
  Select_Lex sel;
 
1796
  LOOKUP_FIELD_VALUES lookup_field_vals;
 
1797
  bool with_i_schema;
 
1798
  vector<LEX_STRING*> db_names, table_names;
 
1799
  COND *partial_cond= 0;
 
1800
  uint32_t derived_tables= lex->derived_tables;
 
1801
  int error= 1;
 
1802
  Open_tables_state open_tables_state_backup;
 
1803
  Query_tables_list query_tables_list_backup;
 
1804
  uint32_t table_open_method;
 
1805
  bool old_value= session->no_warnings_for_error;
 
1806
 
 
1807
  /*
 
1808
    We should not introduce deadlocks even if we already have some
 
1809
    tables open and locked, since we won't lock tables which we will
 
1810
    open and will ignore possible name-locks for these tables.
 
1811
  */
 
1812
  session->reset_n_backup_open_tables_state(&open_tables_state_backup);
 
1813
 
 
1814
  tables->table_open_method= table_open_method=
 
1815
    get_table_open_method(tables, schema_table);
 
1816
  /*
 
1817
    this branch processes SHOW FIELDS, SHOW INDEXES commands.
 
1818
    see sql_parse.cc, prepare_schema_table() function where
 
1819
    this values are initialized
 
1820
  */
 
1821
  if (lsel && lsel->table_list.first)
 
1822
  {
 
1823
    error= fill_schema_show_cols_or_idxs(session, tables, schema_table,
 
1824
                                         &open_tables_state_backup);
 
1825
    goto err;
 
1826
  }
 
1827
 
 
1828
  if (get_lookup_field_values(session, cond, tables, &lookup_field_vals))
 
1829
  {
 
1830
    error= 0;
 
1831
    goto err;
 
1832
  }
 
1833
 
 
1834
  if (!lookup_field_vals.wild_db_value && !lookup_field_vals.wild_table_value)
 
1835
  {
 
1836
    /*
 
1837
      if lookup value is empty string then
 
1838
      it's impossible table name or db name
 
1839
    */
 
1840
    if ((lookup_field_vals.db_value.str && !lookup_field_vals.db_value.str[0]) ||
 
1841
        (lookup_field_vals.table_value.str && !lookup_field_vals.table_value.str[0]))
 
1842
    {
 
1843
      error= 0;
 
1844
      goto err;
 
1845
    }
 
1846
  }
 
1847
 
 
1848
  if (lookup_field_vals.db_value.length &&
 
1849
      !lookup_field_vals.wild_db_value)
 
1850
    tables->has_db_lookup_value= true;
 
1851
 
 
1852
  if (lookup_field_vals.table_value.length &&
 
1853
      !lookup_field_vals.wild_table_value)
 
1854
    tables->has_table_lookup_value= true;
 
1855
 
 
1856
  if (tables->has_db_lookup_value && tables->has_table_lookup_value)
 
1857
    partial_cond= 0;
 
1858
  else
 
1859
    partial_cond= make_cond_for_info_schema(cond, tables);
 
1860
 
 
1861
  if (lex->describe)
 
1862
  {
 
1863
    /* EXPLAIN SELECT */
 
1864
    error= 0;
 
1865
    goto err;
 
1866
  }
 
1867
 
 
1868
  table->setWriteSet();
 
1869
  if (make_db_list(session, db_names, &lookup_field_vals, &with_i_schema))
 
1870
    goto err;
 
1871
 
 
1872
  for (vector<LEX_STRING*>::iterator db_name= db_names.begin(); db_name != db_names.end(); ++db_name )
 
1873
  {
 
1874
    session->no_warnings_for_error= 1;
 
1875
    table_names.clear();
 
1876
    int res= make_table_name_list(session, table_names, lex,
 
1877
                                  &lookup_field_vals,
 
1878
                                  with_i_schema, *db_name);
 
1879
 
 
1880
    if (res == 2)   /* Not fatal error, continue */
 
1881
      continue;
 
1882
 
 
1883
    if (res)
 
1884
      goto err;
 
1885
 
 
1886
    
 
1887
    for (vector<LEX_STRING*>::iterator table_name= table_names.begin(); table_name != table_names.end(); ++table_name)
 
1888
    {
 
1889
      table->restoreRecordAsDefault();
 
1890
      table->field[schema_table->getFirstColumnIndex()]->
 
1891
        store((*db_name)->str, (*db_name)->length, system_charset_info);
 
1892
      table->field[schema_table->getSecondColumnIndex()]->
 
1893
        store((*table_name)->str, (*table_name)->length, system_charset_info);
 
1894
 
 
1895
      if (!partial_cond || partial_cond->val_int())
 
1896
      {
 
1897
        /*
 
1898
          If table is I_S.tables and open_table_method is 0 (eg SKIP_OPEN)
 
1899
          we can skip table opening and we don't have lookup value for
 
1900
          table name or lookup value is wild string(table name list is
 
1901
          already created by make_table_name_list() function).
 
1902
        */
 
1903
        if (! table_open_method &&
 
1904
            schema_table->getTableName().compare("TABLES") == 0 &&
 
1905
            (! lookup_field_vals.table_value.length ||
 
1906
             lookup_field_vals.wild_table_value))
 
1907
        {
 
1908
          if (schema_table_store_record(session, table))
 
1909
            goto err;      /* Out of space in temporary table */
 
1910
          continue;
 
1911
        }
 
1912
 
 
1913
        /* SHOW Table NAMES command */
 
1914
        if (schema_table->getTableName().compare("TABLE_NAMES") == 0)
 
1915
        {
 
1916
          if (fill_schema_table_names(session, tables->table, *db_name,
 
1917
                                      *table_name, with_i_schema))
 
1918
            continue;
 
1919
        }
 
1920
        else
 
1921
        {
 
1922
          if (!(table_open_method & ~OPEN_FRM_ONLY) &&
 
1923
              !with_i_schema)
 
1924
          {
 
1925
            if (!fill_schema_table_from_frm(session, tables, schema_table, *db_name,
 
1926
                                            *table_name))
 
1927
              continue;
 
1928
          }
 
1929
 
 
1930
          LEX_STRING tmp_lex_string, orig_db_name;
 
1931
          /*
 
1932
            Set the parent lex of 'sel' because it is needed by
 
1933
            sel.init_query() which is called inside make_table_list.
 
1934
          */
 
1935
          session->no_warnings_for_error= 1;
 
1936
          sel.parent_lex= lex;
 
1937
          /* db_name can be changed in make_table_list() func */
 
1938
          if (!session->make_lex_string(&orig_db_name, (*db_name)->str,
 
1939
                                        (*db_name)->length, false))
 
1940
            goto err;
 
1941
 
 
1942
          if (make_table_list(session, &sel, *db_name, *table_name))
 
1943
            goto err;
 
1944
 
 
1945
          TableList *show_table_list= (TableList*) sel.table_list.first;
 
1946
          lex->all_selects_list= &sel;
 
1947
          lex->derived_tables= 0;
 
1948
          lex->sql_command= SQLCOM_SHOW_FIELDS;
 
1949
          show_table_list->i_s_requested_object=
 
1950
            schema_table->getRequestedObject();
 
1951
          res= session->openTables(show_table_list, DRIZZLE_LOCK_IGNORE_FLUSH);
 
1952
          lex->sql_command= save_sql_command;
 
1953
          /*
 
1954
            XXX->  show_table_list has a flag i_is_requested,
 
1955
            and when it's set, openTables()
 
1956
            can return an error without setting an error message
 
1957
            in Session, which is a hack. This is why we have to
 
1958
            check for res, then for session->is_error() only then
 
1959
            for session->main_da.sql_errno().
 
1960
          */
 
1961
          if (res && session->is_error() &&
 
1962
              session->main_da.sql_errno() == ER_NO_SUCH_TABLE)
 
1963
          {
 
1964
            /*
 
1965
              Hide error for not existing table.
 
1966
              This error can occur for example when we use
 
1967
              where condition with db name and table name and this
 
1968
              table does not exist.
 
1969
            */
 
1970
            res= 0;
 
1971
            session->clear_error();
 
1972
          }
 
1973
          else
 
1974
          {
 
1975
            /*
 
1976
              We should use show_table_list->alias instead of
 
1977
              show_table_list->table_name because table_name
 
1978
              could be changed during opening of I_S tables. It's safe
 
1979
              to use alias because alias contains original table name
 
1980
              in this case.
 
1981
            */
 
1982
            session->make_lex_string(&tmp_lex_string, show_table_list->alias,
 
1983
                                     strlen(show_table_list->alias), false);
 
1984
            res= schema_table->processTable(session, show_table_list, table,
 
1985
                                            res, &orig_db_name,
 
1986
                                            &tmp_lex_string);
 
1987
            session->close_tables_for_reopen(&show_table_list);
 
1988
          }
 
1989
          assert(!lex->query_tables_own_last);
 
1990
          if (res)
 
1991
            goto err;
 
1992
        }
 
1993
      }
 
1994
    }
 
1995
    /*
 
1996
      If we have information schema its always the first table and only
 
1997
      the first table. Reset for other tables.
 
1998
    */
 
1999
    with_i_schema= 0;
 
2000
  }
 
2001
 
 
2002
  error= 0;
 
2003
 
 
2004
err:
 
2005
  session->restore_backup_open_tables_state(&open_tables_state_backup);
 
2006
  lex->derived_tables= derived_tables;
 
2007
  lex->all_selects_list= old_all_select_lex;
 
2008
  lex->sql_command= save_sql_command;
 
2009
  session->no_warnings_for_error= old_value;
 
2010
  return(error);
 
2011
}
 
2012
 
 
2013
 
 
2014
/**
 
2015
  @brief    Store field characteristics into appropriate I_S table columns
 
2016
 
 
2017
  @param[in]      table             I_S table
 
2018
  @param[in]      field             processed field
 
2019
  @param[in]      cs                I_S table charset
 
2020
  @param[in]      offset            offset from beginning of table
 
2021
                                    to DATE_TYPE column in I_S table
 
2022
 
 
2023
  @return         void
 
2024
*/
 
2025
 
 
2026
static void store_column_type(Table *table, Field *field,
 
2027
                              const CHARSET_INFO * const cs,
 
2028
                              uint32_t offset)
 
2029
{
 
2030
  bool is_blob;
 
2031
  int decimals, field_length;
 
2032
  const char *tmp_buff;
 
2033
  char column_type_buff[MAX_FIELD_WIDTH];
 
2034
  String column_type(column_type_buff, sizeof(column_type_buff), cs);
 
2035
 
 
2036
  field->sql_type(column_type);
 
2037
  /* DTD_IDENTIFIER column */
 
2038
  table->field[offset + 7]->store(column_type.ptr(), column_type.length(), cs);
 
2039
  table->field[offset + 7]->set_notnull();
 
2040
  tmp_buff= strchr(column_type.ptr(), '(');
 
2041
  /* DATA_TYPE column */
 
2042
  table->field[offset]->store(column_type.ptr(),
 
2043
                         (tmp_buff ? tmp_buff - column_type.ptr() :
 
2044
                          column_type.length()), cs);
 
2045
  is_blob= (field->type() == DRIZZLE_TYPE_BLOB);
 
2046
  if (field->has_charset() || is_blob ||
 
2047
      field->real_type() == DRIZZLE_TYPE_VARCHAR)  // For varbinary type
 
2048
  {
 
2049
    uint32_t octet_max_length= field->max_display_length();
 
2050
    if (is_blob && octet_max_length != (uint32_t) 4294967295U)
 
2051
      octet_max_length /= field->charset()->mbmaxlen;
 
2052
    int64_t char_max_len= is_blob ?
 
2053
      (int64_t) octet_max_length / field->charset()->mbminlen :
 
2054
      (int64_t) octet_max_length / field->charset()->mbmaxlen;
 
2055
    /* CHARACTER_MAXIMUM_LENGTH column*/
 
2056
    table->field[offset + 1]->store(char_max_len, true);
 
2057
    table->field[offset + 1]->set_notnull();
 
2058
    /* CHARACTER_OCTET_LENGTH column */
 
2059
    table->field[offset + 2]->store((int64_t) octet_max_length, true);
 
2060
    table->field[offset + 2]->set_notnull();
 
2061
  }
 
2062
 
 
2063
  /*
 
2064
    Calculate field_length and decimals.
 
2065
    They are set to -1 if they should not be set (we should return NULL)
 
2066
  */
 
2067
 
 
2068
  decimals= field->decimals();
 
2069
  switch (field->type()) {
 
2070
  case DRIZZLE_TYPE_NEWDECIMAL:
 
2071
    field_length= ((Field_new_decimal*) field)->precision;
 
2072
    break;
 
2073
  case DRIZZLE_TYPE_LONG:
 
2074
  case DRIZZLE_TYPE_LONGLONG:
 
2075
    field_length= field->max_display_length() - 1;
 
2076
    break;
 
2077
  case DRIZZLE_TYPE_DOUBLE:
 
2078
    field_length= field->field_length;
 
2079
    if (decimals == NOT_FIXED_DEC)
 
2080
      decimals= -1;                           // return NULL
 
2081
    break;
 
2082
  default:
 
2083
    field_length= decimals= -1;
 
2084
    break;
 
2085
  }
 
2086
 
 
2087
  /* NUMERIC_PRECISION column */
 
2088
  if (field_length >= 0)
 
2089
  {
 
2090
    table->field[offset + 3]->store((int64_t) field_length, true);
 
2091
    table->field[offset + 3]->set_notnull();
 
2092
  }
 
2093
  /* NUMERIC_SCALE column */
 
2094
  if (decimals >= 0)
 
2095
  {
 
2096
    table->field[offset + 4]->store((int64_t) decimals, true);
 
2097
    table->field[offset + 4]->set_notnull();
 
2098
  }
 
2099
  if (field->has_charset())
 
2100
  {
 
2101
    /* CHARACTER_SET_NAME column*/
 
2102
    tmp_buff= field->charset()->csname;
 
2103
    table->field[offset + 5]->store(tmp_buff, strlen(tmp_buff), cs);
 
2104
    table->field[offset + 5]->set_notnull();
 
2105
    /* COLLATION_NAME column */
 
2106
    tmp_buff= field->charset()->name;
 
2107
    table->field[offset + 6]->store(tmp_buff, strlen(tmp_buff), cs);
 
2108
    table->field[offset + 6]->set_notnull();
 
2109
  }
 
2110
}
 
2111
 
 
2112
 
 
2113
int plugin::InfoSchemaMethods::processTable(Session *session, TableList *tables,
 
2114
                                    Table *table, bool res,
 
2115
                                    LEX_STRING *db_name,
 
2116
                                    LEX_STRING *table_name) const
 
2117
{
 
2118
  LEX *lex= session->lex;
 
2119
  const char *wild= lex->wild ? lex->wild->ptr() : NULL;
 
2120
  const CHARSET_INFO * const cs= system_charset_info;
 
2121
  Table *show_table;
 
2122
  TableShare *show_table_share;
 
2123
  Field **ptr, *field, *timestamp_field;
 
2124
  int count;
 
2125
 
 
2126
  if (res)
 
2127
  {
 
2128
    if (lex->sql_command != SQLCOM_SHOW_FIELDS)
 
2129
    {
 
2130
      /*
 
2131
        I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS
 
2132
        rather than in SHOW COLUMNS
 
2133
      */
 
2134
      if (session->is_error())
 
2135
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
2136
                     session->main_da.sql_errno(), session->main_da.message());
 
2137
      session->clear_error();
 
2138
      res= 0;
 
2139
    }
 
2140
    return(res);
 
2141
  }
 
2142
 
 
2143
  show_table= tables->table;
 
2144
  show_table_share= show_table->s;
 
2145
  count= 0;
 
2146
 
 
2147
  if (tables->schema_table)
 
2148
  {
 
2149
    ptr= show_table->field;
 
2150
    timestamp_field= show_table->timestamp_field;
 
2151
  }
 
2152
  else
 
2153
  {
 
2154
    ptr= show_table_share->field;
 
2155
    timestamp_field= show_table_share->timestamp_field;
 
2156
  }
 
2157
 
 
2158
  /* For the moment we just set everything to read */
 
2159
  if (!show_table->read_set)
 
2160
  {
 
2161
    show_table->def_read_set.setAll();
 
2162
    show_table->read_set= &show_table->def_read_set;
 
2163
  }
 
2164
  show_table->use_all_columns();               // Required for default
 
2165
 
 
2166
  for (; (field= *ptr) ; ptr++)
 
2167
  {
 
2168
    unsigned char *pos;
 
2169
    char tmp[MAX_FIELD_WIDTH];
 
2170
    String type(tmp,sizeof(tmp), system_charset_info);
 
2171
    char *end;
 
2172
 
 
2173
    /* to satisfy 'field->val_str' ASSERTs */
 
2174
    field->table= show_table;
 
2175
    show_table->in_use= session;
 
2176
 
 
2177
    if (wild && wild[0] &&
 
2178
        wild_case_compare(system_charset_info, field->field_name,wild))
 
2179
      continue;
 
2180
 
 
2181
    count++;
 
2182
    /* Get default row, with all NULL fields set to NULL */
 
2183
    table->restoreRecordAsDefault();
 
2184
 
 
2185
    table->field[1]->store(db_name->str, db_name->length, cs);
 
2186
    table->field[2]->store(table_name->str, table_name->length, cs);
 
2187
    table->field[3]->store(field->field_name, strlen(field->field_name),
 
2188
                           cs);
 
2189
    table->field[4]->store((int64_t) count, true);
 
2190
 
 
2191
    if (get_field_default_value(timestamp_field, field, &type, 0))
 
2192
    {
 
2193
      table->field[5]->store(type.ptr(), type.length(), cs);
 
2194
      table->field[5]->set_notnull();
 
2195
    }
 
2196
    pos=(unsigned char*) ((field->flags & NOT_NULL_FLAG) ?  "NO" : "YES");
 
2197
    table->field[6]->store((const char*) pos,
 
2198
                           strlen((const char*) pos), cs);
 
2199
    store_column_type(table, field, cs, 7);
 
2200
 
 
2201
    pos=(unsigned char*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
 
2202
                 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
 
2203
                 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
 
2204
    table->field[15]->store((const char*) pos,
 
2205
                            strlen((const char*) pos), cs);
 
2206
 
 
2207
    end= tmp;
 
2208
    if (field->unireg_check == Field::NEXT_NUMBER)
 
2209
      table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs);
 
2210
    if (timestamp_field == field &&
 
2211
        field->unireg_check != Field::TIMESTAMP_DN_FIELD)
 
2212
      table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"),
 
2213
                              cs);
 
2214
    table->field[18]->store(field->comment.str, field->comment.length, cs);
 
2215
    {
 
2216
      enum column_format_type column_format= (enum column_format_type)
 
2217
        ((field->flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
 
2218
      pos=(unsigned char*)"Default";
 
2219
      table->field[19]->store((const char*) pos,
 
2220
                              strlen((const char*) pos), cs);
 
2221
      pos=(unsigned char*)(column_format == COLUMN_FORMAT_TYPE_DEFAULT ? "Default" :
 
2222
                   column_format == COLUMN_FORMAT_TYPE_FIXED ? "Fixed" :
 
2223
                                                             "Dynamic");
 
2224
      table->field[20]->store((const char*) pos,
 
2225
                              strlen((const char*) pos), cs);
 
2226
    }
 
2227
    if (schema_table_store_record(session, table))
 
2228
      return(1);
 
2229
  }
 
2230
  return(0);
 
2231
}
 
2232
 
 
2233
 
 
2234
/*
 
2235
  Find schema_tables elment by name
 
2236
 
 
2237
  SYNOPSIS
 
2238
    find_schema_table()
 
2239
    table_name          table name
 
2240
 
 
2241
  RETURN
 
2242
    0   table not found
 
2243
    #   pointer to 'schema_tables' element
 
2244
*/
 
2245
 
 
2246
plugin::InfoSchema *find_schema_table(const char* table_name)
 
2247
{
 
2248
  
 
2249
  plugin::Registry &plugins= plugin::Registry::singleton();
 
2250
  return plugins.info_schema.getTable(table_name);
 
2251
}
 
2252
 
 
2253
 
 
2254
Table *plugin::InfoSchemaMethods::createSchemaTable(Session *session, TableList *table_list)
 
2255
  const
 
2256
{
 
2257
  int field_count= 0;
 
2258
  Item *item;
 
2259
  Table *table;
 
2260
  List<Item> field_list;
 
2261
  const CHARSET_INFO * const cs= system_charset_info;
 
2262
  const plugin::InfoSchema::Columns &columns= table_list->schema_table->getColumns();
 
2263
  plugin::InfoSchema::Columns::const_iterator iter= columns.begin();
 
2264
 
 
2265
  while (iter != columns.end())
 
2266
  {
 
2267
    const plugin::ColumnInfo *column= *iter;
 
2268
    switch (column->getType()) {
 
2269
    case DRIZZLE_TYPE_LONG:
 
2270
    case DRIZZLE_TYPE_LONGLONG:
 
2271
      if (!(item= new Item_return_int(column->getName().c_str(),
 
2272
                                      column->getLength(),
 
2273
                                      column->getType(),
 
2274
                                      column->getValue())))
 
2275
      {
 
2276
        return(0);
 
2277
      }
 
2278
      item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
 
2279
      break;
 
2280
    case DRIZZLE_TYPE_DATE:
 
2281
    case DRIZZLE_TYPE_TIMESTAMP:
 
2282
    case DRIZZLE_TYPE_DATETIME:
 
2283
      if (!(item=new Item_return_date_time(column->getName().c_str(),
 
2284
                                           column->getType())))
 
2285
      {
 
2286
        return(0);
 
2287
      }
 
2288
      break;
 
2289
    case DRIZZLE_TYPE_DOUBLE:
 
2290
      if ((item= new Item_float(column->getName().c_str(), 0.0, NOT_FIXED_DEC,
 
2291
                           column->getLength())) == NULL)
 
2292
        return NULL;
 
2293
      break;
 
2294
    case DRIZZLE_TYPE_NEWDECIMAL:
 
2295
      if (!(item= new Item_decimal((int64_t) column->getValue(), false)))
 
2296
      {
 
2297
        return(0);
 
2298
      }
 
2299
      item->unsigned_flag= (column->getFlags() & MY_I_S_UNSIGNED);
 
2300
      item->decimals= column->getLength() % 10;
 
2301
      item->max_length= (column->getLength()/100)%100;
 
2302
      if (item->unsigned_flag == 0)
 
2303
        item->max_length+= 1;
 
2304
      if (item->decimals > 0)
 
2305
        item->max_length+= 1;
 
2306
      item->set_name(column->getName().c_str(),
 
2307
                     column->getName().length(), cs);
 
2308
      break;
 
2309
    case DRIZZLE_TYPE_BLOB:
 
2310
      if (!(item= new Item_blob(column->getName().c_str(),
 
2311
                                column->getLength())))
 
2312
      {
 
2313
        return(0);
 
2314
      }
 
2315
      break;
 
2316
    default:
 
2317
      if (!(item= new Item_empty_string("", column->getLength(), cs)))
 
2318
      {
 
2319
        return(0);
 
2320
      }
 
2321
      item->set_name(column->getName().c_str(),
 
2322
                     column->getName().length(), cs);
 
2323
      break;
 
2324
    }
 
2325
    field_list.push_back(item);
 
2326
    item->maybe_null= (column->getFlags() & MY_I_S_MAYBE_NULL);
 
2327
    field_count++;
 
2328
    ++iter;
 
2329
  }
 
2330
  Tmp_Table_Param *tmp_table_param =
 
2331
    (Tmp_Table_Param*) (session->alloc(sizeof(Tmp_Table_Param)));
 
2332
  tmp_table_param->init();
 
2333
  tmp_table_param->table_charset= cs;
 
2334
  tmp_table_param->field_count= field_count;
 
2335
  tmp_table_param->schema_table= 1;
 
2336
  Select_Lex *select_lex= session->lex->current_select;
 
2337
  if (!(table= create_tmp_table(session, tmp_table_param,
 
2338
                                field_list, (order_st*) 0, 0, 0,
 
2339
                                (select_lex->options | session->options |
 
2340
                                 TMP_TABLE_ALL_COLUMNS),
 
2341
                                HA_POS_ERROR, table_list->alias)))
 
2342
    return(0);
 
2343
  my_bitmap_map* bitmaps=
 
2344
    (my_bitmap_map*) session->alloc(bitmap_buffer_size(field_count));
 
2345
  table->def_read_set.init((my_bitmap_map*) bitmaps, field_count);
 
2346
  table->read_set= &table->def_read_set;
 
2347
  table->read_set->clearAll();
 
2348
  table_list->schema_table_param= tmp_table_param;
 
2349
  return(table);
 
2350
}
 
2351
 
 
2352
 
 
2353
/*
 
2354
  For old SHOW compatibility. It is used when
 
2355
  old SHOW doesn't have generated column names
 
2356
  Make list of fields for SHOW
 
2357
 
 
2358
  SYNOPSIS
 
2359
    plugin::InfoSchemaMethods::oldFormat()
 
2360
    session                     thread handler
 
2361
    schema_table        pointer to 'schema_tables' element
 
2362
 
 
2363
  RETURN
 
2364
   1    error
 
2365
   0    success
 
2366
*/
 
2367
 
 
2368
int plugin::InfoSchemaMethods::oldFormat(Session *session, plugin::InfoSchema *schema_table)
 
2369
  const
 
2370
{
 
2371
  Name_resolution_context *context= &session->lex->select_lex.context;
 
2372
  const plugin::InfoSchema::Columns columns= schema_table->getColumns();
 
2373
  plugin::InfoSchema::Columns::const_iterator iter= columns.begin();
 
2374
 
 
2375
  while (iter != columns.end())
 
2376
  {
 
2377
    const plugin::ColumnInfo *column= *iter;
 
2378
    if (column->getOldName().length() != 0)
 
2379
    {
 
2380
      Item_field *field= new Item_field(context,
 
2381
                                        NULL, NULL,
 
2382
                                        column->getName().c_str());
 
2383
      if (field)
 
2384
      {
 
2385
        field->set_name(column->getOldName().c_str(),
 
2386
                        column->getOldName().length(),
 
2387
                        system_charset_info);
 
2388
        if (session->add_item_to_list(field))
 
2389
          return 1;
 
2390
      }
 
2391
    }
 
2392
    ++iter;
 
2393
  }
 
2394
  return 0;
 
2395
}
 
2396
 
 
2397
 
 
2398
/*
 
2399
  Create information_schema table
 
2400
 
 
2401
  SYNOPSIS
 
2402
  mysql_schema_table()
 
2403
    session                thread handler
 
2404
    lex                pointer to LEX
 
2405
    table_list         pointer to table_list
 
2406
 
 
2407
  RETURN
 
2408
    true on error
 
2409
*/
 
2410
 
 
2411
bool mysql_schema_table(Session *session, LEX *, TableList *table_list)
 
2412
{
 
2413
  Table *table;
 
2414
  if (!(table= table_list->schema_table->createSchemaTable(session, table_list)))
 
2415
    return true;
 
2416
  table->s->tmp_table= SYSTEM_TMP_TABLE;
 
2417
  /*
 
2418
    This test is necessary to make
 
2419
    case insensitive file systems +
 
2420
    upper case table names(information schema tables) +
 
2421
    views
 
2422
    working correctly
 
2423
  */
 
2424
  if (table_list->schema_table_name)
 
2425
    table->alias_name_used= my_strcasecmp(table_alias_charset,
 
2426
                                          table_list->schema_table_name,
 
2427
                                          table_list->alias);
 
2428
  table_list->table_name= table->s->table_name.str;
 
2429
  table_list->table_name_length= table->s->table_name.length;
 
2430
  table_list->table= table;
 
2431
  table->next= session->derived_tables;
 
2432
  session->derived_tables= table;
 
2433
  table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
 
2434
 
 
2435
  return false;
 
2436
}
 
2437
 
 
2438
 
 
2439
/*
 
2440
  Generate select from information_schema table
 
2441
 
 
2442
  SYNOPSIS
 
2443
    make_schema_select()
 
2444
    session                  thread handler
 
2445
    sel                  pointer to Select_Lex
 
2446
    schema_table_name    name of 'schema_tables' element
 
2447
 
 
2448
  RETURN
 
2449
    true on error
 
2450
*/
 
2451
 
 
2452
bool make_schema_select(Session *session, Select_Lex *sel,
 
2453
                        const string& schema_table_name)
 
2454
{
 
2455
  plugin::InfoSchema *schema_table= find_schema_table(schema_table_name.c_str());
 
2456
  LEX_STRING db, table;
 
2457
  /*
 
2458
     We have to make non const db_name & table_name
 
2459
     because of lower_case_table_names
 
2460
  */
 
2461
  session->make_lex_string(&db, INFORMATION_SCHEMA_NAME.c_str(),
 
2462
                       INFORMATION_SCHEMA_NAME.length(), 0);
 
2463
  session->make_lex_string(&table, schema_table->getTableName().c_str(),
 
2464
                           schema_table->getTableName().length(), 0);
 
2465
  if (schema_table->oldFormat(session, schema_table) ||   /* Handle old syntax */
 
2466
      ! sel->add_table_to_list(session, new Table_ident(db, table), 0, 0, TL_READ))
 
2467
  {
 
2468
    return true;
 
2469
  }
 
2470
  return false;
 
2471
}
 
2472
 
 
2473
 
 
2474
/*
 
2475
  Fill temporary schema tables before SELECT
 
2476
 
 
2477
  SYNOPSIS
 
2478
    get_schema_tables_result()
 
2479
    join  join which use schema tables
 
2480
    executed_place place where I_S table processed
 
2481
 
 
2482
  RETURN
 
2483
    false success
 
2484
    true  error
 
2485
*/
 
2486
 
 
2487
bool get_schema_tables_result(JOIN *join,
 
2488
                              enum enum_schema_table_state executed_place)
 
2489
{
 
2490
  JoinTable *tmp_join_tab= join->join_tab+join->tables;
 
2491
  Session *session= join->session;
 
2492
  LEX *lex= session->lex;
 
2493
  bool result= 0;
 
2494
 
 
2495
  session->no_warnings_for_error= 1;
 
2496
  for (JoinTable *tab= join->join_tab; tab < tmp_join_tab; tab++)
 
2497
  {
 
2498
    if (!tab->table || !tab->table->pos_in_table_list)
 
2499
      break;
 
2500
 
 
2501
    TableList *table_list= tab->table->pos_in_table_list;
 
2502
    if (table_list->schema_table)
 
2503
    {
 
2504
      bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
 
2505
                          lex->current_select->master_unit()->item);
 
2506
 
 
2507
 
 
2508
      /* skip I_S optimizations specific to get_all_tables */
 
2509
      if (session->lex->describe &&
 
2510
          (table_list->schema_table->isOptimizationPossible() != true))
 
2511
      {
 
2512
        continue;
 
2513
      }
 
2514
 
 
2515
      /*
 
2516
        If schema table is already processed and
 
2517
        the statement is not a subselect then
 
2518
        we don't need to fill this table again.
 
2519
        If schema table is already processed and
 
2520
        schema_table_state != executed_place then
 
2521
        table is already processed and
 
2522
        we should skip second data processing.
 
2523
      */
 
2524
      if (table_list->schema_table_state &&
 
2525
          (!is_subselect || table_list->schema_table_state != executed_place))
 
2526
        continue;
 
2527
 
 
2528
      /*
 
2529
        if table is used in a subselect and
 
2530
        table has been processed earlier with the same
 
2531
        'executed_place' value then we should refresh the table.
 
2532
      */
 
2533
      if (table_list->schema_table_state && is_subselect)
 
2534
      {
 
2535
        table_list->table->file->extra(HA_EXTRA_NO_CACHE);
 
2536
        table_list->table->file->extra(HA_EXTRA_RESET_STATE);
 
2537
        table_list->table->file->ha_delete_all_rows();
 
2538
        table_list->table->free_io_cache();
 
2539
        table_list->table->filesort_free_buffers(true);
 
2540
        table_list->table->null_row= 0;
 
2541
      }
 
2542
      else
 
2543
        table_list->table->file->stats.records= 0;
 
2544
 
 
2545
      if (table_list->schema_table->fillTable(session, table_list,
 
2546
                                               tab->select_cond))
 
2547
      {
 
2548
        result= 1;
 
2549
        join->error= 1;
 
2550
        tab->read_record.file= table_list->table->file;
 
2551
        table_list->schema_table_state= executed_place;
 
2552
        break;
 
2553
      }
 
2554
      tab->read_record.file= table_list->table->file;
 
2555
      table_list->schema_table_state= executed_place;
 
2556
    }
 
2557
  }
 
2558
  session->no_warnings_for_error= 0;
 
2559
  return(result);
 
2560
}