~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

  • Committer: Monty Taylor
  • Date: 2009-12-14 22:00:27 UTC
  • mto: (1241.9.10 out-of-tree)
  • mto: This revision was merged to the branch mainline in revision 1250.
  • Revision ID: mordred@inaugust.com-20091214220027-kpmfbl452nctzc0g
pandora-build v0.85 - Fixed C++ standard setting.

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