~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/show.cc

Merging Stewart's show create table patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
#include "drizzled/pthread_globals.h"
49
49
#include "drizzled/internal/m_string.h"
50
50
#include "drizzled/internal/my_sys.h"
 
51
#include "drizzled/message/statement_transform.h"
 
52
 
51
53
 
52
54
#include <sys/stat.h>
53
55
 
68
70
  return str ? str : "<nil>";
69
71
}
70
72
 
71
 
static void store_key_options(String *packet, Table *table, KeyInfo *key_info);
72
 
 
73
 
 
74
73
int wild_case_compare(const CHARSET_INFO * const cs, const char *str, const char *wildstr)
75
74
{
76
75
  register int flag;
287
286
 
288
287
#define LIST_PROCESS_HOST_LEN 64
289
288
 
290
 
static bool get_field_default_value(Field *timestamp_field,
291
 
                                    Field *field, String *def_value,
292
 
                                    bool quoted)
293
 
{
294
 
  bool has_default;
295
 
  bool has_now_default;
296
 
 
297
 
  /*
298
 
     We are using CURRENT_TIMESTAMP instead of NOW because it is
299
 
     more standard
300
 
  */
301
 
  has_now_default= (timestamp_field == field &&
302
 
                    field->unireg_check != Field::TIMESTAMP_UN_FIELD);
303
 
 
304
 
  has_default= (field->type() != DRIZZLE_TYPE_BLOB &&
305
 
                !(field->flags & NO_DEFAULT_VALUE_FLAG) &&
306
 
                field->unireg_check != Field::NEXT_NUMBER);
307
 
 
308
 
  def_value->length(0);
309
 
  if (has_default)
310
 
  {
311
 
    if (has_now_default)
312
 
      def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP"));
313
 
    else if (!field->is_null())
314
 
    {                                             // Not null by default
315
 
      char tmp[MAX_FIELD_WIDTH];
316
 
      String type(tmp, sizeof(tmp), field->charset());
317
 
      field->val_str(&type);
318
 
      if (type.length())
319
 
      {
320
 
        String def_val;
321
 
        uint32_t dummy_errors;
322
 
        /* convert to system_charset_info == utf8 */
323
 
        def_val.copy(type.ptr(), type.length(), field->charset(),
324
 
                     system_charset_info, &dummy_errors);
325
 
        if (quoted)
326
 
          append_unescaped(def_value, def_val.ptr(), def_val.length());
327
 
        else
328
 
          def_value->append(def_val.ptr(), def_val.length());
329
 
      }
330
 
      else if (quoted)
331
 
        def_value->append(STRING_WITH_LEN("''"));
332
 
    }
333
 
    else if (field->maybe_null() && quoted)
334
 
      def_value->append(STRING_WITH_LEN("NULL"));    // Null as default
335
 
    else
336
 
      return false;
337
 
  }
338
 
  return has_default;
339
 
}
340
 
 
341
289
/*
342
290
  Build a CREATE TABLE statement for a table.
343
291
 
358
306
 
359
307
int store_create_info(TableList *table_list, String *packet, bool is_if_not_exists)
360
308
{
361
 
  List<Item> field_list;
362
 
  char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH];
363
 
  const char *alias;
364
 
  string buff;
365
 
  String type(tmp, sizeof(tmp), system_charset_info);
366
 
  String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info);
367
 
  Field **ptr,*field;
368
 
  uint32_t primary_key;
369
 
  KeyInfo *key_info;
370
309
  Table *table= table_list->table;
371
 
  Cursor *cursor= table->cursor;
372
 
  HA_CREATE_INFO create_info;
373
 
  my_bitmap_map *old_map;
374
310
 
375
311
  table->restoreRecordAsDefault(); // Get empty record
376
312
 
377
 
  if (table->getShare()->getType())
378
 
    packet->append(STRING_WITH_LEN("CREATE TEMPORARY TABLE "));
379
 
  else
380
 
    packet->append(STRING_WITH_LEN("CREATE TABLE "));
381
 
  if (is_if_not_exists)
382
 
    packet->append(STRING_WITH_LEN("IF NOT EXISTS "));
383
 
  alias= table->getShare()->getTableName();
384
 
 
385
 
  packet->append_identifier(alias, strlen(alias));
386
 
  packet->append(STRING_WITH_LEN(" (\n"));
387
 
  /*
388
 
    We need this to get default values from the table
389
 
    We have to restore the read_set if we are called from insert in case
390
 
    of row based replication.
391
 
  */
392
 
  old_map= table->use_all_columns(table->read_set);
393
 
 
394
 
  for (ptr= table->getFields() ; (field= *ptr); ptr++)
395
 
  {
396
 
    uint32_t flags = field->flags;
397
 
 
398
 
    if (ptr != table->getFields())
399
 
      packet->append(STRING_WITH_LEN(",\n"));
400
 
 
401
 
    packet->append(STRING_WITH_LEN("  "));
402
 
    packet->append_identifier(field->field_name, strlen(field->field_name));
403
 
    packet->append(' ');
404
 
    // check for surprises from the previous call to Field::sql_type()
405
 
    if (type.ptr() != tmp)
406
 
      type.set(tmp, sizeof(tmp), system_charset_info);
407
 
    else
408
 
      type.set_charset(system_charset_info);
409
 
 
410
 
    field->sql_type(type);
411
 
    packet->append(type.ptr(), type.length(), system_charset_info);
412
 
 
413
 
    if (field->has_charset())
414
 
    {
415
 
      /*
416
 
        For string types dump collation name only if
417
 
        collation is not primary for the given charset
418
 
      */
419
 
      if (!(field->charset()->state & MY_CS_PRIMARY))
420
 
      {
421
 
        packet->append(STRING_WITH_LEN(" COLLATE "));
422
 
        packet->append(field->charset()->name);
423
 
      }
424
 
    }
425
 
 
426
 
    if (flags & NOT_NULL_FLAG)
427
 
      packet->append(STRING_WITH_LEN(" NOT NULL"));
428
 
    else if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
429
 
    {
430
 
      /*
431
 
        TIMESTAMP field require explicit NULL flag, because unlike
432
 
        all other fields they are treated as NOT NULL by default.
433
 
      */
434
 
      packet->append(STRING_WITH_LEN(" NULL"));
435
 
    }
436
 
    {
437
 
      /*
438
 
        Add field flags about FIELD FORMAT (FIXED or DYNAMIC)
439
 
        and about STORAGE (DISK or MEMORY).
440
 
      */
441
 
      enum column_format_type column_format= (enum column_format_type)
442
 
        ((flags >> COLUMN_FORMAT_FLAGS) & COLUMN_FORMAT_MASK);
443
 
      if (column_format)
444
 
      {
445
 
        packet->append(STRING_WITH_LEN(" /*!"));
446
 
        packet->append(STRING_WITH_LEN(" COLUMN_FORMAT"));
447
 
        if (column_format == COLUMN_FORMAT_TYPE_FIXED)
448
 
          packet->append(STRING_WITH_LEN(" FIXED */"));
449
 
        else
450
 
          packet->append(STRING_WITH_LEN(" DYNAMIC */"));
451
 
      }
452
 
    }
453
 
    if (get_field_default_value(table->timestamp_field, field, &def_value, 1))
454
 
    {
455
 
      packet->append(STRING_WITH_LEN(" DEFAULT "));
456
 
      packet->append(def_value.ptr(), def_value.length(), system_charset_info);
457
 
    }
458
 
 
459
 
    if (table->timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD)
460
 
      packet->append(STRING_WITH_LEN(" ON UPDATE CURRENT_TIMESTAMP"));
461
 
 
462
 
    if (field->unireg_check == Field::NEXT_NUMBER)
463
 
      packet->append(STRING_WITH_LEN(" AUTO_INCREMENT"));
464
 
 
465
 
    if (field->comment.length)
466
 
    {
467
 
      packet->append(STRING_WITH_LEN(" COMMENT "));
468
 
      append_unescaped(packet, field->comment.str, field->comment.length);
469
 
    }
470
 
  }
471
 
 
472
 
  key_info= table->key_info;
473
 
  memset(&create_info, 0, sizeof(create_info));
474
 
 
475
 
  primary_key= table->getShare()->getPrimaryKey();
476
 
 
477
 
  for (uint32_t i=0 ; i < table->getShare()->sizeKeys() ; i++,key_info++)
478
 
  {
479
 
    KeyPartInfo *key_part= key_info->key_part;
480
 
    bool found_primary=0;
481
 
    packet->append(STRING_WITH_LEN(",\n  "));
482
 
 
483
 
    if (i == primary_key && is_primary_key(key_info))
484
 
    {
485
 
      found_primary=1;
486
 
      /*
487
 
        No space at end, because a space will be added after where the
488
 
        identifier would go, but that is not added for primary key.
489
 
      */
490
 
      packet->append(STRING_WITH_LEN("PRIMARY KEY"));
491
 
    }
492
 
    else if (key_info->flags & HA_NOSAME)
493
 
      packet->append(STRING_WITH_LEN("UNIQUE KEY "));
494
 
    else
495
 
      packet->append(STRING_WITH_LEN("KEY "));
496
 
 
497
 
    if (!found_primary)
498
 
     packet->append_identifier(key_info->name, strlen(key_info->name));
499
 
 
500
 
    packet->append(STRING_WITH_LEN(" ("));
501
 
 
502
 
    for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
503
 
    {
504
 
      if (j)
505
 
        packet->append(',');
506
 
 
507
 
      if (key_part->field)
508
 
        packet->append_identifier(key_part->field->field_name,
509
 
                                  strlen(key_part->field->field_name));
510
 
      if (key_part->field &&
511
 
          (key_part->length !=
512
 
           table->getField(key_part->fieldnr-1)->key_length()))
513
 
      {
514
 
        buff.assign("(");
515
 
        buff.append(to_string((int32_t) key_part->length /
516
 
                              key_part->field->charset()->mbmaxlen));
517
 
        buff.append(")");
518
 
        packet->append(buff.c_str(), buff.length());
519
 
      }
520
 
    }
521
 
    packet->append(')');
522
 
    store_key_options(packet, table, key_info);
523
 
  }
524
 
 
525
 
  /*
526
 
    Get possible foreign key definitions stored in InnoDB and append them
527
 
    to the CREATE TABLE statement
528
 
  */
529
 
 
530
 
  if ((for_str= cursor->get_foreign_key_create_info()))
531
 
  {
532
 
    packet->append(for_str, strlen(for_str));
533
 
    cursor->free_foreign_key_create_info(for_str);
534
 
  }
535
 
 
536
 
  packet->append(STRING_WITH_LEN("\n)"));
537
 
  {
538
 
    /*
539
 
      Get possible table space definitions and append them
540
 
      to the CREATE TABLE statement
541
 
    */
542
 
 
543
 
    /* 
544
 
      We should always store engine since we will now be 
545
 
      making sure engines accept options (aka... no
546
 
      dangling arguments for engines.
547
 
    */
548
 
    packet->append(STRING_WITH_LEN(" ENGINE="));
549
 
    packet->append(cursor->getEngine()->getName().c_str());
550
 
 
551
 
    size_t num_engine_options= table->getShare()->getTableProto()->engine().options_size();
552
 
    for (size_t x= 0; x < num_engine_options; ++x)
553
 
    {
554
 
      const message::Engine::Option &option= table->getShare()->getTableProto()->engine().options(x);
555
 
      packet->append(" ");
556
 
      packet->append(option.name().c_str());
557
 
      packet->append("=");
558
 
      append_unescaped(packet, option.state().c_str(), option.state().length());
559
 
    }
560
 
 
561
 
    if (table->getShare()->block_size)
562
 
    {
563
 
      packet->append(STRING_WITH_LEN(" BLOCK_SIZE="));
564
 
      buff= to_string(table->getShare()->block_size);
565
 
      packet->append(buff.c_str(), buff.length());
566
 
    }
567
 
    table->cursor->append_create_info(packet);
568
 
    if (table->getMutableShare()->hasComment() && table->getMutableShare()->getCommentLength())
569
 
    {
570
 
      packet->append(STRING_WITH_LEN(" COMMENT="));
571
 
      append_unescaped(packet, table->getMutableShare()->getComment(),
572
 
                       table->getMutableShare()->getCommentLength());
573
 
    }
574
 
  }
575
 
  table->restore_column_map(old_map);
 
313
  string create_sql;
 
314
 
 
315
  enum drizzled::message::TransformSqlError transform_err;
 
316
 
 
317
  (void)is_if_not_exists;
 
318
 
 
319
  transform_err= message::transformTableDefinitionToSql(*(table->getShare()->getTableProto()),
 
320
                                                        create_sql,
 
321
                                                        message::DRIZZLE,
 
322
                                                        false);
 
323
 
 
324
  packet->append(create_sql.c_str(), create_sql.length(), default_charset_info);
 
325
 
576
326
  return(0);
577
327
}
578
328
 
579
 
static void store_key_options(String *packet, Table *, KeyInfo *key_info)
580
 
{
581
 
  if (key_info->algorithm == HA_KEY_ALG_BTREE)
582
 
    packet->append(STRING_WITH_LEN(" USING BTREE"));
583
 
 
584
 
  if (key_info->algorithm == HA_KEY_ALG_HASH)
585
 
    packet->append(STRING_WITH_LEN(" USING HASH"));
586
 
 
587
 
  assert(test(key_info->flags & HA_USES_COMMENT) ==
588
 
              (key_info->comment.length > 0));
589
 
  if (key_info->flags & HA_USES_COMMENT)
590
 
  {
591
 
    packet->append(STRING_WITH_LEN(" COMMENT "));
592
 
    append_unescaped(packet, key_info->comment.str,
593
 
                     key_info->comment.length);
594
 
  }
595
 
}
596
 
 
597
 
 
598
329
/****************************************************************************
599
330
  Return info about all processes
600
331
  returns for each thread: thread id, user, host, db, command, info