~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_share.cc

  • Committer: Brian Aker
  • Date: 2010-05-13 07:52:42 UTC
  • mfrom: (1527.1.4 staging)
  • Revision ID: brian@gaz-20100513075242-gyzfi5c4nb9x4919
Merge of TableShare keynames typelib removal.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
 
4
 *  Copyright (C) 2010 Brian Aker
4
5
 *  Copyright (C) 2009 Sun Microsystems
5
6
 *
6
7
 *  This program is free software; you can redistribute it and/or modify
27
28
#include "config.h"
28
29
 
29
30
#include <pthread.h>
 
31
#include <float.h>
 
32
 
 
33
#include <sys/types.h>
 
34
#include <sys/stat.h>
 
35
#include <fcntl.h>
 
36
 
30
37
 
31
38
#include <cassert>
32
39
 
36
43
#include "drizzled/pthread_globals.h"
37
44
#include "drizzled/internal/my_pthread.h"
38
45
 
 
46
#include "drizzled/session.h"
 
47
 
 
48
#include "drizzled/charset.h"
 
49
#include "drizzled/internal/m_string.h"
 
50
#include "drizzled/internal/my_sys.h"
 
51
 
 
52
#include "drizzled/item/string.h"
 
53
#include "drizzled/item/int.h"
 
54
#include "drizzled/item/decimal.h"
 
55
#include "drizzled/item/float.h"
 
56
#include "drizzled/item/null.h"
 
57
#include "drizzled/temporal.h"
 
58
 
39
59
using namespace std;
40
60
 
41
61
namespace drizzled
228
248
  }
229
249
  
230
250
  TableIdentifier identifier(share->getSchemaName(), share->getTableName());
231
 
  if (open_table_def(*session, identifier, share))
 
251
  if (share->open_table_def(*session, identifier))
232
252
  {
233
253
    *error= share->error;
234
254
    table_def_cache.erase(key_string);
276
296
  }
277
297
}
278
298
 
 
299
/* Get column name from column hash */
 
300
 
 
301
static unsigned char *get_field_name(Field **buff, size_t *length, bool)
 
302
{
 
303
  *length= (uint32_t) strlen((*buff)->field_name);
 
304
  return (unsigned char*) (*buff)->field_name;
 
305
}
 
306
 
 
307
static enum_field_types proto_field_type_to_drizzle_type(uint32_t proto_field_type)
 
308
{
 
309
  enum_field_types field_type;
 
310
 
 
311
  switch(proto_field_type)
 
312
  {
 
313
  case message::Table::Field::INTEGER:
 
314
    field_type= DRIZZLE_TYPE_LONG;
 
315
    break;
 
316
  case message::Table::Field::DOUBLE:
 
317
    field_type= DRIZZLE_TYPE_DOUBLE;
 
318
    break;
 
319
  case message::Table::Field::TIMESTAMP:
 
320
    field_type= DRIZZLE_TYPE_TIMESTAMP;
 
321
    break;
 
322
  case message::Table::Field::BIGINT:
 
323
    field_type= DRIZZLE_TYPE_LONGLONG;
 
324
    break;
 
325
  case message::Table::Field::DATETIME:
 
326
    field_type= DRIZZLE_TYPE_DATETIME;
 
327
    break;
 
328
  case message::Table::Field::DATE:
 
329
    field_type= DRIZZLE_TYPE_DATE;
 
330
    break;
 
331
  case message::Table::Field::VARCHAR:
 
332
    field_type= DRIZZLE_TYPE_VARCHAR;
 
333
    break;
 
334
  case message::Table::Field::DECIMAL:
 
335
    field_type= DRIZZLE_TYPE_DECIMAL;
 
336
    break;
 
337
  case message::Table::Field::ENUM:
 
338
    field_type= DRIZZLE_TYPE_ENUM;
 
339
    break;
 
340
  case message::Table::Field::BLOB:
 
341
    field_type= DRIZZLE_TYPE_BLOB;
 
342
    break;
 
343
  default:
 
344
    field_type= DRIZZLE_TYPE_LONG; /* Set value to kill GCC warning */
 
345
    assert(1);
 
346
  }
 
347
 
 
348
  return field_type;
 
349
}
 
350
 
 
351
static Item *default_value_item(enum_field_types field_type,
 
352
                                const CHARSET_INFO *charset,
 
353
                                bool default_null, const string *default_value,
 
354
                                const string *default_bin_value)
 
355
{
 
356
  Item *default_item= NULL;
 
357
  int error= 0;
 
358
 
 
359
  if (default_null)
 
360
  {
 
361
    return new Item_null();
 
362
  }
 
363
 
 
364
  switch(field_type)
 
365
  {
 
366
  case DRIZZLE_TYPE_LONG:
 
367
  case DRIZZLE_TYPE_LONGLONG:
 
368
    default_item= new Item_int(default_value->c_str(),
 
369
                               (int64_t) internal::my_strtoll10(default_value->c_str(),
 
370
                                                                NULL,
 
371
                                                                &error),
 
372
                               default_value->length());
 
373
    break;
 
374
  case DRIZZLE_TYPE_DOUBLE:
 
375
    default_item= new Item_float(default_value->c_str(),
 
376
                                 default_value->length());
 
377
    break;
 
378
  case DRIZZLE_TYPE_NULL:
 
379
    assert(false);
 
380
  case DRIZZLE_TYPE_TIMESTAMP:
 
381
  case DRIZZLE_TYPE_DATETIME:
 
382
  case DRIZZLE_TYPE_DATE:
 
383
    if (default_value->compare("NOW()") == 0)
 
384
      break;
 
385
  case DRIZZLE_TYPE_ENUM:
 
386
    default_item= new Item_string(default_value->c_str(),
 
387
                                  default_value->length(),
 
388
                                  system_charset_info);
 
389
    break;
 
390
  case DRIZZLE_TYPE_VARCHAR:
 
391
  case DRIZZLE_TYPE_BLOB: /* Blob is here due to TINYTEXT. Feel the hate. */
 
392
    if (charset==&my_charset_bin)
 
393
    {
 
394
      default_item= new Item_string(default_bin_value->c_str(),
 
395
                                    default_bin_value->length(),
 
396
                                    &my_charset_bin);
 
397
    }
 
398
    else
 
399
    {
 
400
      default_item= new Item_string(default_value->c_str(),
 
401
                                    default_value->length(),
 
402
                                    system_charset_info);
 
403
    }
 
404
    break;
 
405
  case DRIZZLE_TYPE_DECIMAL:
 
406
    default_item= new Item_decimal(default_value->c_str(),
 
407
                                   default_value->length(),
 
408
                                   system_charset_info);
 
409
    break;
 
410
  }
 
411
 
 
412
  return default_item;
 
413
}
 
414
 
 
415
 
 
416
 
279
417
/**
280
418
 * @todo
281
419
 *
365
503
  newed(true)
366
504
{
367
505
  memset(&name_hash, 0, sizeof(HASH));
368
 
  memset(&keynames, 0, sizeof(TYPELIB));
369
506
  memset(&fieldnames, 0, sizeof(TYPELIB));
370
507
 
371
508
  table_charset= 0;
418
555
  newed= true;
419
556
}
420
557
 
 
558
int TableShare::inner_parse_table_proto(Session& session, message::Table &table)
 
559
{
 
560
  TableShare *share= this;
 
561
  int local_error= 0;
 
562
 
 
563
  if (! table.IsInitialized())
 
564
  {
 
565
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), table.InitializationErrorString().c_str());
 
566
    return ER_CORRUPT_TABLE_DEFINITION;
 
567
  }
 
568
 
 
569
  share->setTableProto(new(nothrow) message::Table(table));
 
570
 
 
571
  share->storage_engine= plugin::StorageEngine::findByName(session, table.engine().name());
 
572
  assert(share->storage_engine); // We use an assert() here because we should never get this far and still have no suitable engine.
 
573
 
 
574
  message::Table::TableOptions table_options;
 
575
 
 
576
  if (table.has_options())
 
577
    table_options= table.options();
 
578
 
 
579
  uint32_t local_db_create_options= 0;
 
580
 
 
581
  if (table_options.pack_record())
 
582
    local_db_create_options|= HA_OPTION_PACK_RECORD;
 
583
 
 
584
  /* local_db_create_options was stored as 2 bytes in FRM
 
585
     Any HA_OPTION_ that doesn't fit into 2 bytes was silently truncated away.
 
586
   */
 
587
  share->db_create_options= (local_db_create_options & 0x0000FFFF);
 
588
  share->db_options_in_use= share->db_create_options;
 
589
 
 
590
  share->row_type= table_options.has_row_type() ?
 
591
    (enum row_type) table_options.row_type() : ROW_TYPE_DEFAULT;
 
592
 
 
593
  share->block_size= table_options.has_block_size() ?
 
594
    table_options.block_size() : 0;
 
595
 
 
596
  share->table_charset= get_charset(table_options.has_collation_id()?
 
597
                                    table_options.collation_id() : 0);
 
598
 
 
599
  if (!share->table_charset)
 
600
  {
 
601
    /* unknown charset in head[38] or pre-3.23 frm */
 
602
    if (use_mb(default_charset_info))
 
603
    {
 
604
      /* Warn that we may be changing the size of character columns */
 
605
      errmsg_printf(ERRMSG_LVL_WARN,
 
606
                    _("'%s' had no or invalid character set, "
 
607
                      "and default character set is multi-byte, "
 
608
                      "so character column sizes may have changed"),
 
609
                    share->getPath());
 
610
    }
 
611
    share->table_charset= default_charset_info;
 
612
  }
 
613
 
 
614
  share->db_record_offset= 1;
 
615
 
 
616
  share->blob_ptr_size= portable_sizeof_char_ptr; // more bonghits.
 
617
 
 
618
  share->keys= table.indexes_size();
 
619
 
 
620
  share->key_parts= 0;
 
621
  for (int indx= 0; indx < table.indexes_size(); indx++)
 
622
    share->key_parts+= table.indexes(indx).index_part_size();
 
623
 
 
624
  share->key_info= (KEY*) share->alloc_root( table.indexes_size() * sizeof(KEY) +share->key_parts*sizeof(KEY_PART_INFO));
 
625
 
 
626
  KEY_PART_INFO *key_part;
 
627
 
 
628
  key_part= reinterpret_cast<KEY_PART_INFO*>
 
629
    (share->key_info+table.indexes_size());
 
630
 
 
631
 
 
632
  ulong *rec_per_key= (ulong*) share->alloc_root(sizeof(ulong*)*share->key_parts);
 
633
 
 
634
  KEY* keyinfo= share->key_info;
 
635
  for (int keynr= 0; keynr < table.indexes_size(); keynr++, keyinfo++)
 
636
  {
 
637
    message::Table::Index indx= table.indexes(keynr);
 
638
 
 
639
    keyinfo->table= 0;
 
640
    keyinfo->flags= 0;
 
641
 
 
642
    if (indx.is_unique())
 
643
      keyinfo->flags|= HA_NOSAME;
 
644
 
 
645
    if (indx.has_options())
 
646
    {
 
647
      message::Table::Index::IndexOptions indx_options= indx.options();
 
648
      if (indx_options.pack_key())
 
649
        keyinfo->flags|= HA_PACK_KEY;
 
650
 
 
651
      if (indx_options.var_length_key())
 
652
        keyinfo->flags|= HA_VAR_LENGTH_PART;
 
653
 
 
654
      if (indx_options.null_part_key())
 
655
        keyinfo->flags|= HA_NULL_PART_KEY;
 
656
 
 
657
      if (indx_options.binary_pack_key())
 
658
        keyinfo->flags|= HA_BINARY_PACK_KEY;
 
659
 
 
660
      if (indx_options.has_partial_segments())
 
661
        keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
 
662
 
 
663
      if (indx_options.auto_generated_key())
 
664
        keyinfo->flags|= HA_GENERATED_KEY;
 
665
 
 
666
      if (indx_options.has_key_block_size())
 
667
      {
 
668
        keyinfo->flags|= HA_USES_BLOCK_SIZE;
 
669
        keyinfo->block_size= indx_options.key_block_size();
 
670
      }
 
671
      else
 
672
      {
 
673
        keyinfo->block_size= 0;
 
674
      }
 
675
    }
 
676
 
 
677
    switch (indx.type())
 
678
    {
 
679
    case message::Table::Index::UNKNOWN_INDEX:
 
680
      keyinfo->algorithm= HA_KEY_ALG_UNDEF;
 
681
      break;
 
682
    case message::Table::Index::BTREE:
 
683
      keyinfo->algorithm= HA_KEY_ALG_BTREE;
 
684
      break;
 
685
    case message::Table::Index::HASH:
 
686
      keyinfo->algorithm= HA_KEY_ALG_HASH;
 
687
      break;
 
688
 
 
689
    default:
 
690
      /* TODO: suitable warning ? */
 
691
      keyinfo->algorithm= HA_KEY_ALG_UNDEF;
 
692
      break;
 
693
    }
 
694
 
 
695
    keyinfo->key_length= indx.key_length();
 
696
 
 
697
    keyinfo->key_parts= indx.index_part_size();
 
698
 
 
699
    keyinfo->key_part= key_part;
 
700
    keyinfo->rec_per_key= rec_per_key;
 
701
 
 
702
    for (unsigned int partnr= 0;
 
703
         partnr < keyinfo->key_parts;
 
704
         partnr++, key_part++)
 
705
    {
 
706
      message::Table::Index::IndexPart part;
 
707
      part= indx.index_part(partnr);
 
708
 
 
709
      *rec_per_key++= 0;
 
710
 
 
711
      key_part->field= NULL;
 
712
      key_part->fieldnr= part.fieldnr() + 1; // start from 1.
 
713
      key_part->null_bit= 0;
 
714
      /* key_part->null_offset is only set if null_bit (see later) */
 
715
      /* key_part->key_type= */ /* I *THINK* this may be okay.... */
 
716
      /* key_part->type ???? */
 
717
      key_part->key_part_flag= 0;
 
718
      if (part.has_in_reverse_order())
 
719
        key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
 
720
 
 
721
      key_part->length= part.compare_length();
 
722
 
 
723
      key_part->store_length= key_part->length;
 
724
 
 
725
      /* key_part->offset is set later */
 
726
      key_part->key_type= part.key_type();
 
727
    }
 
728
 
 
729
    if (! indx.has_comment())
 
730
    {
 
731
      keyinfo->comment.length= 0;
 
732
      keyinfo->comment.str= NULL;
 
733
    }
 
734
    else
 
735
    {
 
736
      keyinfo->flags|= HA_USES_COMMENT;
 
737
      keyinfo->comment.length= indx.comment().length();
 
738
      keyinfo->comment.str= share->strmake_root(indx.comment().c_str(), keyinfo->comment.length);
 
739
    }
 
740
 
 
741
    keyinfo->name= share->strmake_root(indx.name().c_str(), indx.name().length());
 
742
 
 
743
    addKeyName(string(keyinfo->name, indx.name().length()));
 
744
  }
 
745
 
 
746
  share->keys_for_keyread.reset();
 
747
  set_prefix(share->keys_in_use, share->keys);
 
748
 
 
749
  share->fields= table.field_size();
 
750
 
 
751
  share->field= (Field**) share->alloc_root(((share->fields+1) * sizeof(Field*)));
 
752
  share->field[share->fields]= NULL;
 
753
 
 
754
  uint32_t local_null_fields= 0;
 
755
  share->reclength= 0;
 
756
 
 
757
  vector<uint32_t> field_offsets;
 
758
  vector<uint32_t> field_pack_length;
 
759
 
 
760
  field_offsets.resize(share->fields);
 
761
  field_pack_length.resize(share->fields);
 
762
 
 
763
  uint32_t interval_count= 0;
 
764
  uint32_t interval_parts= 0;
 
765
 
 
766
  uint32_t stored_columns_reclength= 0;
 
767
 
 
768
  for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
 
769
  {
 
770
    message::Table::Field pfield= table.field(fieldnr);
 
771
    if (pfield.constraints().is_nullable())
 
772
      local_null_fields++;
 
773
 
 
774
    enum_field_types drizzle_field_type=
 
775
      proto_field_type_to_drizzle_type(pfield.type());
 
776
 
 
777
    field_offsets[fieldnr]= stored_columns_reclength;
 
778
 
 
779
    /* the below switch is very similar to
 
780
       CreateField::create_length_to_internal_length in field.cc
 
781
       (which should one day be replace by just this code)
 
782
    */
 
783
    switch(drizzle_field_type)
 
784
    {
 
785
    case DRIZZLE_TYPE_BLOB:
 
786
    case DRIZZLE_TYPE_VARCHAR:
 
787
      {
 
788
        message::Table::Field::StringFieldOptions field_options= pfield.string_options();
 
789
 
 
790
        const CHARSET_INFO *cs= get_charset(field_options.has_collation_id() ?
 
791
                                            field_options.collation_id() : 0);
 
792
 
 
793
        if (! cs)
 
794
          cs= default_charset_info;
 
795
 
 
796
        field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type,
 
797
                                                     field_options.length() * cs->mbmaxlen);
 
798
      }
 
799
      break;
 
800
    case DRIZZLE_TYPE_ENUM:
 
801
      {
 
802
        message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
 
803
 
 
804
        field_pack_length[fieldnr]=
 
805
          get_enum_pack_length(field_options.field_value_size());
 
806
 
 
807
        interval_count++;
 
808
        interval_parts+= field_options.field_value_size();
 
809
      }
 
810
      break;
 
811
    case DRIZZLE_TYPE_DECIMAL:
 
812
      {
 
813
        message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
 
814
 
 
815
        field_pack_length[fieldnr]= my_decimal_get_binary_size(fo.precision(), fo.scale());
 
816
      }
 
817
      break;
 
818
    default:
 
819
      /* Zero is okay here as length is fixed for other types. */
 
820
      field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
 
821
    }
 
822
 
 
823
    share->reclength+= field_pack_length[fieldnr];
 
824
    stored_columns_reclength+= field_pack_length[fieldnr];
 
825
  }
 
826
 
 
827
  /* data_offset added to stored_rec_length later */
 
828
  share->stored_rec_length= stored_columns_reclength;
 
829
 
 
830
  share->null_fields= local_null_fields;
 
831
 
 
832
  ulong null_bits= local_null_fields;
 
833
  if (! table_options.pack_record())
 
834
    null_bits++;
 
835
  ulong data_offset= (null_bits + 7)/8;
 
836
 
 
837
 
 
838
  share->reclength+= data_offset;
 
839
  share->stored_rec_length+= data_offset;
 
840
 
 
841
  ulong local_rec_buff_length;
 
842
 
 
843
  local_rec_buff_length= ALIGN_SIZE(share->reclength + 1);
 
844
  share->rec_buff_length= local_rec_buff_length;
 
845
 
 
846
  unsigned char* record= NULL;
 
847
 
 
848
  if (! (record= (unsigned char *) share->alloc_root(local_rec_buff_length)))
 
849
    abort();
 
850
 
 
851
  memset(record, 0, local_rec_buff_length);
 
852
 
 
853
  int null_count= 0;
 
854
 
 
855
  if (! table_options.pack_record())
 
856
  {
 
857
    null_count++; // one bit for delete mark.
 
858
    *record|= 1;
 
859
  }
 
860
 
 
861
  share->default_values= record;
 
862
 
 
863
  if (interval_count)
 
864
  {
 
865
    share->intervals= (TYPELIB *) share->alloc_root(interval_count*sizeof(TYPELIB));
 
866
  }
 
867
  else
 
868
  {
 
869
    share->intervals= NULL;
 
870
  }
 
871
 
 
872
  share->fieldnames.type_names= (const char **) share->alloc_root((share->fields + 1) * sizeof(char*));
 
873
 
 
874
  share->fieldnames.type_lengths= (unsigned int *) share->alloc_root((share->fields + 1) * sizeof(unsigned int));
 
875
 
 
876
  share->fieldnames.type_names[share->fields]= NULL;
 
877
  share->fieldnames.type_lengths[share->fields]= 0;
 
878
  share->fieldnames.count= share->fields;
 
879
 
 
880
 
 
881
  /* Now fix the TYPELIBs for the intervals (enum values)
 
882
     and field names.
 
883
   */
 
884
 
 
885
  uint32_t interval_nr= 0;
 
886
 
 
887
  for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
 
888
  {
 
889
    message::Table::Field pfield= table.field(fieldnr);
 
890
 
 
891
    /* field names */
 
892
    share->fieldnames.type_names[fieldnr]= share->strmake_root(pfield.name().c_str(), pfield.name().length());
 
893
 
 
894
    share->fieldnames.type_lengths[fieldnr]= pfield.name().length();
 
895
 
 
896
    /* enum typelibs */
 
897
    if (pfield.type() != message::Table::Field::ENUM)
 
898
      continue;
 
899
 
 
900
    message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
 
901
 
 
902
    const CHARSET_INFO *charset= get_charset(field_options.has_collation_id() ?
 
903
                                             field_options.collation_id() : 0);
 
904
 
 
905
    if (! charset)
 
906
      charset= default_charset_info;
 
907
 
 
908
    TYPELIB *t= &(share->intervals[interval_nr]);
 
909
 
 
910
    t->type_names= (const char**)share->alloc_root((field_options.field_value_size() + 1) * sizeof(char*));
 
911
 
 
912
    t->type_lengths= (unsigned int*) share->alloc_root((field_options.field_value_size() + 1) * sizeof(unsigned int));
 
913
 
 
914
    t->type_names[field_options.field_value_size()]= NULL;
 
915
    t->type_lengths[field_options.field_value_size()]= 0;
 
916
 
 
917
    t->count= field_options.field_value_size();
 
918
    t->name= NULL;
 
919
 
 
920
    for (int n= 0; n < field_options.field_value_size(); n++)
 
921
    {
 
922
      t->type_names[n]= share->strmake_root(field_options.field_value(n).c_str(), field_options.field_value(n).length());
 
923
 
 
924
      /* 
 
925
       * Go ask the charset what the length is as for "" length=1
 
926
       * and there's stripping spaces or some other crack going on.
 
927
       */
 
928
      uint32_t lengthsp;
 
929
      lengthsp= charset->cset->lengthsp(charset,
 
930
                                        t->type_names[n],
 
931
                                        field_options.field_value(n).length());
 
932
      t->type_lengths[n]= lengthsp;
 
933
    }
 
934
    interval_nr++;
 
935
  }
 
936
 
 
937
 
 
938
  /* and read the fields */
 
939
  interval_nr= 0;
 
940
 
 
941
  bool use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
 
942
 
 
943
  if (use_hash)
 
944
    use_hash= ! hash_init(&share->name_hash,
 
945
                          system_charset_info,
 
946
                          share->fields,
 
947
                          0,
 
948
                          0,
 
949
                          (hash_get_key) get_field_name,
 
950
                          0,
 
951
                          0);
 
952
 
 
953
  unsigned char* null_pos= record;;
 
954
  int null_bit_pos= (table_options.pack_record()) ? 0 : 1;
 
955
 
 
956
  for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
 
957
  {
 
958
    message::Table::Field pfield= table.field(fieldnr);
 
959
 
 
960
    enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
 
961
 
 
962
    switch (pfield.format())
 
963
    {
 
964
    case message::Table::Field::DefaultFormat:
 
965
      column_format= COLUMN_FORMAT_TYPE_DEFAULT;
 
966
      break;
 
967
    case message::Table::Field::FixedFormat:
 
968
      column_format= COLUMN_FORMAT_TYPE_FIXED;
 
969
      break;
 
970
    case message::Table::Field::DynamicFormat:
 
971
      column_format= COLUMN_FORMAT_TYPE_DYNAMIC;
 
972
      break;
 
973
    default:
 
974
      assert(1);
 
975
    }
 
976
 
 
977
    Field::utype unireg_type= Field::NONE;
 
978
 
 
979
    if (pfield.has_numeric_options() &&
 
980
        pfield.numeric_options().is_autoincrement())
 
981
    {
 
982
      unireg_type= Field::NEXT_NUMBER;
 
983
    }
 
984
 
 
985
    if (pfield.has_options() &&
 
986
        pfield.options().has_default_value() &&
 
987
        pfield.options().default_value().compare("NOW()") == 0)
 
988
    {
 
989
      if (pfield.options().has_update_value() &&
 
990
          pfield.options().update_value().compare("NOW()") == 0)
 
991
      {
 
992
        unireg_type= Field::TIMESTAMP_DNUN_FIELD;
 
993
      }
 
994
      else if (! pfield.options().has_update_value())
 
995
      {
 
996
        unireg_type= Field::TIMESTAMP_DN_FIELD;
 
997
      }
 
998
      else
 
999
        assert(1); // Invalid update value.
 
1000
    }
 
1001
    else if (pfield.has_options() &&
 
1002
             pfield.options().has_update_value() &&
 
1003
             pfield.options().update_value().compare("NOW()") == 0)
 
1004
    {
 
1005
      unireg_type= Field::TIMESTAMP_UN_FIELD;
 
1006
    }
 
1007
 
 
1008
    LEX_STRING comment;
 
1009
    if (!pfield.has_comment())
 
1010
    {
 
1011
      comment.str= (char*)"";
 
1012
      comment.length= 0;
 
1013
    }
 
1014
    else
 
1015
    {
 
1016
      size_t len= pfield.comment().length();
 
1017
      const char* str= pfield.comment().c_str();
 
1018
 
 
1019
      comment.str= share->strmake_root(str, len);
 
1020
      comment.length= len;
 
1021
    }
 
1022
 
 
1023
    enum_field_types field_type;
 
1024
 
 
1025
    field_type= proto_field_type_to_drizzle_type(pfield.type());
 
1026
 
 
1027
    const CHARSET_INFO *charset= &my_charset_bin;
 
1028
 
 
1029
    if (field_type == DRIZZLE_TYPE_BLOB ||
 
1030
        field_type == DRIZZLE_TYPE_VARCHAR)
 
1031
    {
 
1032
      message::Table::Field::StringFieldOptions field_options= pfield.string_options();
 
1033
 
 
1034
      charset= get_charset(field_options.has_collation_id() ?
 
1035
                           field_options.collation_id() : 0);
 
1036
 
 
1037
      if (! charset)
 
1038
        charset= default_charset_info;
 
1039
    }
 
1040
 
 
1041
    if (field_type == DRIZZLE_TYPE_ENUM)
 
1042
    {
 
1043
      message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
 
1044
 
 
1045
      charset= get_charset(field_options.has_collation_id()?
 
1046
                           field_options.collation_id() : 0);
 
1047
 
 
1048
      if (! charset)
 
1049
              charset= default_charset_info;
 
1050
    }
 
1051
 
 
1052
    uint8_t decimals= 0;
 
1053
    if (field_type == DRIZZLE_TYPE_DECIMAL
 
1054
        || field_type == DRIZZLE_TYPE_DOUBLE)
 
1055
    {
 
1056
      message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
 
1057
 
 
1058
      if (! pfield.has_numeric_options() || ! fo.has_scale())
 
1059
      {
 
1060
        /*
 
1061
          We don't write the default to table proto so
 
1062
          if no decimals specified for DOUBLE, we use the default.
 
1063
        */
 
1064
        decimals= NOT_FIXED_DEC;
 
1065
      }
 
1066
      else
 
1067
      {
 
1068
        if (fo.scale() > DECIMAL_MAX_SCALE)
 
1069
        {
 
1070
          local_error= 4;
 
1071
 
 
1072
          return local_error;
 
1073
        }
 
1074
        decimals= static_cast<uint8_t>(fo.scale());
 
1075
      }
 
1076
    }
 
1077
 
 
1078
    Item *default_value= NULL;
 
1079
 
 
1080
    if (pfield.options().has_default_value() ||
 
1081
        pfield.options().has_default_null()  ||
 
1082
        pfield.options().has_default_bin_value())
 
1083
    {
 
1084
      default_value= default_value_item(field_type,
 
1085
                                        charset,
 
1086
                                        pfield.options().default_null(),
 
1087
                                        &pfield.options().default_value(),
 
1088
                                        &pfield.options().default_bin_value());
 
1089
    }
 
1090
 
 
1091
 
 
1092
    Table temp_table; /* Use this so that BLOB DEFAULT '' works */
 
1093
    memset(&temp_table, 0, sizeof(temp_table));
 
1094
    temp_table.s= share;
 
1095
    temp_table.in_use= &session;
 
1096
    temp_table.s->db_low_byte_first= true; //Cursor->low_byte_first();
 
1097
    temp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
 
1098
 
 
1099
    uint32_t field_length= 0; //Assignment is for compiler complaint.
 
1100
 
 
1101
    switch (field_type)
 
1102
    {
 
1103
    case DRIZZLE_TYPE_BLOB:
 
1104
    case DRIZZLE_TYPE_VARCHAR:
 
1105
    {
 
1106
      message::Table::Field::StringFieldOptions field_options= pfield.string_options();
 
1107
 
 
1108
      charset= get_charset(field_options.has_collation_id() ?
 
1109
                           field_options.collation_id() : 0);
 
1110
 
 
1111
      if (! charset)
 
1112
        charset= default_charset_info;
 
1113
 
 
1114
      field_length= field_options.length() * charset->mbmaxlen;
 
1115
    }
 
1116
      break;
 
1117
    case DRIZZLE_TYPE_DOUBLE:
 
1118
    {
 
1119
      message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
 
1120
      if (!fo.has_precision() && !fo.has_scale())
 
1121
      {
 
1122
        field_length= DBL_DIG+7;
 
1123
      }
 
1124
      else
 
1125
      {
 
1126
        field_length= fo.precision();
 
1127
      }
 
1128
      if (field_length < decimals &&
 
1129
          decimals != NOT_FIXED_DEC)
 
1130
      {
 
1131
        my_error(ER_M_BIGGER_THAN_D, MYF(0), pfield.name().c_str());
 
1132
        local_error= 1;
 
1133
 
 
1134
        return local_error;
 
1135
      }
 
1136
      break;
 
1137
    }
 
1138
    case DRIZZLE_TYPE_DECIMAL:
 
1139
    {
 
1140
      message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
 
1141
 
 
1142
      field_length= my_decimal_precision_to_length(fo.precision(), fo.scale(),
 
1143
                                                   false);
 
1144
      break;
 
1145
    }
 
1146
    case DRIZZLE_TYPE_TIMESTAMP:
 
1147
    case DRIZZLE_TYPE_DATETIME:
 
1148
      field_length= DateTime::MAX_STRING_LENGTH;
 
1149
      break;
 
1150
    case DRIZZLE_TYPE_DATE:
 
1151
      field_length= Date::MAX_STRING_LENGTH;
 
1152
      break;
 
1153
    case DRIZZLE_TYPE_ENUM:
 
1154
    {
 
1155
      field_length= 0;
 
1156
 
 
1157
      message::Table::Field::EnumerationValues fo= pfield.enumeration_values();
 
1158
 
 
1159
      for (int valnr= 0; valnr < fo.field_value_size(); valnr++)
 
1160
      {
 
1161
        if (fo.field_value(valnr).length() > field_length)
 
1162
        {
 
1163
          field_length= charset->cset->numchars(charset,
 
1164
                                                fo.field_value(valnr).c_str(),
 
1165
                                                fo.field_value(valnr).c_str()
 
1166
                                                + fo.field_value(valnr).length())
 
1167
            * charset->mbmaxlen;
 
1168
        }
 
1169
      }
 
1170
    }
 
1171
    break;
 
1172
    case DRIZZLE_TYPE_LONG:
 
1173
      {
 
1174
        uint32_t sign_len= pfield.constraints().is_unsigned() ? 0 : 1;
 
1175
          field_length= MAX_INT_WIDTH+sign_len;
 
1176
      }
 
1177
      break;
 
1178
    case DRIZZLE_TYPE_LONGLONG:
 
1179
      field_length= MAX_BIGINT_WIDTH;
 
1180
      break;
 
1181
    case DRIZZLE_TYPE_NULL:
 
1182
      abort(); // Programming error
 
1183
    }
 
1184
 
 
1185
    Field* f= share->make_field(record + field_offsets[fieldnr] + data_offset,
 
1186
                                field_length,
 
1187
                                pfield.constraints().is_nullable(),
 
1188
                                null_pos,
 
1189
                                null_bit_pos,
 
1190
                                decimals,
 
1191
                                field_type,
 
1192
                                charset,
 
1193
                                (Field::utype) MTYP_TYPENR(unireg_type),
 
1194
                                ((field_type == DRIZZLE_TYPE_ENUM) ?
 
1195
                                 share->intervals + (interval_nr++)
 
1196
                                 : (TYPELIB*) 0),
 
1197
                                share->fieldnames.type_names[fieldnr]);
 
1198
 
 
1199
    share->field[fieldnr]= f;
 
1200
 
 
1201
    f->init(&temp_table); /* blob default values need table obj */
 
1202
 
 
1203
    if (! (f->flags & NOT_NULL_FLAG))
 
1204
    {
 
1205
      *f->null_ptr|= f->null_bit;
 
1206
      if (! (null_bit_pos= (null_bit_pos + 1) & 7)) /* @TODO Ugh. */
 
1207
        null_pos++;
 
1208
      null_count++;
 
1209
    }
 
1210
 
 
1211
    if (default_value)
 
1212
    {
 
1213
      enum_check_fields old_count_cuted_fields= session.count_cuted_fields;
 
1214
      session.count_cuted_fields= CHECK_FIELD_WARN;
 
1215
      int res= default_value->save_in_field(f, 1);
 
1216
      session.count_cuted_fields= old_count_cuted_fields;
 
1217
      if (res != 0 && res != 3) /* @TODO Huh? */
 
1218
      {
 
1219
        my_error(ER_INVALID_DEFAULT, MYF(0), f->field_name);
 
1220
        local_error= 1;
 
1221
 
 
1222
        return local_error;
 
1223
      }
 
1224
    }
 
1225
    else if (f->real_type() == DRIZZLE_TYPE_ENUM &&
 
1226
             (f->flags & NOT_NULL_FLAG))
 
1227
    {
 
1228
      f->set_notnull();
 
1229
      f->store((int64_t) 1, true);
 
1230
    }
 
1231
    else
 
1232
    {
 
1233
      f->reset();
 
1234
    }
 
1235
 
 
1236
    /* hack to undo f->init() */
 
1237
    f->table= NULL;
 
1238
    f->orig_table= NULL;
 
1239
 
 
1240
    f->field_index= fieldnr;
 
1241
    f->comment= comment;
 
1242
    if (! default_value &&
 
1243
        ! (f->unireg_check==Field::NEXT_NUMBER) &&
 
1244
        (f->flags & NOT_NULL_FLAG) &&
 
1245
        (f->real_type() != DRIZZLE_TYPE_TIMESTAMP))
 
1246
    {
 
1247
      f->flags|= NO_DEFAULT_VALUE_FLAG;
 
1248
    }
 
1249
 
 
1250
    if (f->unireg_check == Field::NEXT_NUMBER)
 
1251
      share->found_next_number_field= &(share->field[fieldnr]);
 
1252
 
 
1253
    if (share->timestamp_field == f)
 
1254
      share->timestamp_field_offset= fieldnr;
 
1255
 
 
1256
    if (use_hash) /* supposedly this never fails... but comments lie */
 
1257
      (void) my_hash_insert(&share->name_hash,
 
1258
                            (unsigned char*)&(share->field[fieldnr]));
 
1259
 
 
1260
  }
 
1261
 
 
1262
  keyinfo= share->key_info;
 
1263
  for (unsigned int keynr= 0; keynr < share->keys; keynr++, keyinfo++)
 
1264
  {
 
1265
    key_part= keyinfo->key_part;
 
1266
 
 
1267
    for (unsigned int partnr= 0;
 
1268
         partnr < keyinfo->key_parts;
 
1269
         partnr++, key_part++)
 
1270
    {
 
1271
      /* 
 
1272
       * Fix up key_part->offset by adding data_offset.
 
1273
       * We really should compute offset as well.
 
1274
       * But at least this way we are a little better.
 
1275
       */
 
1276
      key_part->offset= field_offsets[key_part->fieldnr-1] + data_offset;
 
1277
    }
 
1278
  }
 
1279
 
 
1280
  /*
 
1281
    We need to set the unused bits to 1. If the number of bits is a multiple
 
1282
    of 8 there are no unused bits.
 
1283
  */
 
1284
 
 
1285
  if (null_count & 7)
 
1286
    *(record + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
 
1287
 
 
1288
  share->null_bytes= (null_pos - (unsigned char*) record + (null_bit_pos + 7) / 8);
 
1289
 
 
1290
  share->last_null_bit_pos= null_bit_pos;
 
1291
 
 
1292
  /* Fix key stuff */
 
1293
  if (share->key_parts)
 
1294
  {
 
1295
    uint32_t local_primary_key= 0;
 
1296
    doesKeyNameExist("PRIMARY", local_primary_key);
 
1297
 
 
1298
    keyinfo= share->key_info;
 
1299
    key_part= keyinfo->key_part;
 
1300
 
 
1301
    for (uint32_t key= 0; key < share->keys; key++,keyinfo++)
 
1302
    {
 
1303
      uint32_t usable_parts= 0;
 
1304
 
 
1305
      if (local_primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
 
1306
      {
 
1307
        /*
 
1308
          If the UNIQUE key doesn't have NULL columns and is not a part key
 
1309
          declare this as a primary key.
 
1310
        */
 
1311
        local_primary_key=key;
 
1312
        for (uint32_t i= 0; i < keyinfo->key_parts; i++)
 
1313
        {
 
1314
          uint32_t fieldnr= key_part[i].fieldnr;
 
1315
          if (! fieldnr ||
 
1316
              share->field[fieldnr-1]->null_ptr ||
 
1317
              share->field[fieldnr-1]->key_length() != key_part[i].length)
 
1318
          {
 
1319
            local_primary_key= MAX_KEY; // Can't be used
 
1320
            break;
 
1321
          }
 
1322
        }
 
1323
      }
 
1324
 
 
1325
      for (uint32_t i= 0 ; i < keyinfo->key_parts ; key_part++,i++)
 
1326
      {
 
1327
        Field *local_field;
 
1328
        if (! key_part->fieldnr)
 
1329
        {
 
1330
          return ENOMEM;
 
1331
        }
 
1332
        local_field= key_part->field= share->field[key_part->fieldnr-1];
 
1333
        key_part->type= local_field->key_type();
 
1334
        if (local_field->null_ptr)
 
1335
        {
 
1336
          key_part->null_offset=(uint32_t) ((unsigned char*) local_field->null_ptr - share->default_values);
 
1337
          key_part->null_bit= local_field->null_bit;
 
1338
          key_part->store_length+=HA_KEY_NULL_LENGTH;
 
1339
          keyinfo->flags|=HA_NULL_PART_KEY;
 
1340
          keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
 
1341
          keyinfo->key_length+= HA_KEY_NULL_LENGTH;
 
1342
        }
 
1343
        if (local_field->type() == DRIZZLE_TYPE_BLOB ||
 
1344
            local_field->real_type() == DRIZZLE_TYPE_VARCHAR)
 
1345
        {
 
1346
          if (local_field->type() == DRIZZLE_TYPE_BLOB)
 
1347
            key_part->key_part_flag|= HA_BLOB_PART;
 
1348
          else
 
1349
            key_part->key_part_flag|= HA_VAR_LENGTH_PART;
 
1350
          keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
 
1351
          key_part->store_length+=HA_KEY_BLOB_LENGTH;
 
1352
          keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
 
1353
        }
 
1354
        if (i == 0 && key != local_primary_key)
 
1355
          local_field->flags |= (((keyinfo->flags & HA_NOSAME) &&
 
1356
                            (keyinfo->key_parts == 1)) ?
 
1357
                           UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
 
1358
        if (i == 0)
 
1359
          local_field->key_start.set(key);
 
1360
        if (local_field->key_length() == key_part->length &&
 
1361
            !(local_field->flags & BLOB_FLAG))
 
1362
        {
 
1363
          enum ha_key_alg algo= share->key_info[key].algorithm;
 
1364
          if (share->db_type()->index_flags(algo) & HA_KEYREAD_ONLY)
 
1365
          {
 
1366
            share->keys_for_keyread.set(key);
 
1367
            local_field->part_of_key.set(key);
 
1368
            local_field->part_of_key_not_clustered.set(key);
 
1369
          }
 
1370
          if (share->db_type()->index_flags(algo) & HA_READ_ORDER)
 
1371
            local_field->part_of_sortkey.set(key);
 
1372
        }
 
1373
        if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
 
1374
            usable_parts == i)
 
1375
          usable_parts++;                       // For FILESORT
 
1376
        local_field->flags|= PART_KEY_FLAG;
 
1377
        if (key == local_primary_key)
 
1378
        {
 
1379
          local_field->flags|= PRI_KEY_FLAG;
 
1380
          /*
 
1381
            If this field is part of the primary key and all keys contains
 
1382
            the primary key, then we can use any key to find this column
 
1383
          */
 
1384
          if (share->storage_engine->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX))
 
1385
          {
 
1386
            local_field->part_of_key= share->keys_in_use;
 
1387
            if (local_field->part_of_sortkey.test(key))
 
1388
              local_field->part_of_sortkey= share->keys_in_use;
 
1389
          }
 
1390
        }
 
1391
        if (local_field->key_length() != key_part->length)
 
1392
        {
 
1393
          key_part->key_part_flag|= HA_PART_KEY_SEG;
 
1394
        }
 
1395
      }
 
1396
      keyinfo->usable_key_parts= usable_parts; // Filesort
 
1397
 
 
1398
      set_if_bigger(share->max_key_length,keyinfo->key_length+
 
1399
                    keyinfo->key_parts);
 
1400
      share->total_key_length+= keyinfo->key_length;
 
1401
 
 
1402
      if (keyinfo->flags & HA_NOSAME)
 
1403
      {
 
1404
        set_if_bigger(share->max_unique_length,keyinfo->key_length);
 
1405
      }
 
1406
    }
 
1407
    if (local_primary_key < MAX_KEY &&
 
1408
        (share->keys_in_use.test(local_primary_key)))
 
1409
    {
 
1410
      share->primary_key= local_primary_key;
 
1411
      /*
 
1412
        If we are using an integer as the primary key then allow the user to
 
1413
        refer to it as '_rowid'
 
1414
      */
 
1415
      if (share->key_info[local_primary_key].key_parts == 1)
 
1416
      {
 
1417
        Field *local_field= share->key_info[local_primary_key].key_part[0].field;
 
1418
        if (local_field && local_field->result_type() == INT_RESULT)
 
1419
        {
 
1420
          /* note that fieldnr here (and rowid_field_offset) starts from 1 */
 
1421
          share->rowid_field_offset= (share->key_info[local_primary_key].key_part[0].
 
1422
                                      fieldnr);
 
1423
        }
 
1424
      }
 
1425
    }
 
1426
    else
 
1427
    {
 
1428
      share->primary_key = MAX_KEY; // we do not have a primary key
 
1429
    }
 
1430
  }
 
1431
  else
 
1432
  {
 
1433
    share->primary_key= MAX_KEY;
 
1434
  }
 
1435
 
 
1436
  if (share->found_next_number_field)
 
1437
  {
 
1438
    Field *reg_field= *share->found_next_number_field;
 
1439
    if ((int) (share->next_number_index= (uint32_t)
 
1440
               find_ref_key(share->key_info, share->keys,
 
1441
                            share->default_values, reg_field,
 
1442
                            &share->next_number_key_offset,
 
1443
                            &share->next_number_keypart)) < 0)
 
1444
    {
 
1445
      /* Wrong field definition */
 
1446
      local_error= 4;
 
1447
 
 
1448
      return local_error;
 
1449
    }
 
1450
    else
 
1451
    {
 
1452
      reg_field->flags |= AUTO_INCREMENT_FLAG;
 
1453
    }
 
1454
  }
 
1455
 
 
1456
  if (share->blob_fields)
 
1457
  {
 
1458
    Field **ptr;
 
1459
    uint32_t k, *save;
 
1460
 
 
1461
    /* Store offsets to blob fields to find them fast */
 
1462
    if (!(share->blob_field= save=
 
1463
          (uint*) share->alloc_root((uint32_t) (share->blob_fields* sizeof(uint32_t)))))
 
1464
    {
 
1465
      return local_error;
 
1466
    }
 
1467
    for (k= 0, ptr= share->field ; *ptr ; ptr++, k++)
 
1468
    {
 
1469
      if ((*ptr)->flags & BLOB_FLAG)
 
1470
        (*save++)= k;
 
1471
    }
 
1472
  }
 
1473
 
 
1474
  share->db_low_byte_first= true; // @todo Question this.
 
1475
  share->column_bitmap_size= bitmap_buffer_size(share->fields);
 
1476
 
 
1477
  my_bitmap_map *bitmaps;
 
1478
 
 
1479
  if (!(bitmaps= (my_bitmap_map*) share->alloc_root(share->column_bitmap_size)))
 
1480
  { }
 
1481
  else
 
1482
  {
 
1483
    share->all_set.init(bitmaps, share->fields);
 
1484
    share->all_set.setAll();
 
1485
 
 
1486
    return (0);
 
1487
  }
 
1488
 
 
1489
  return local_error;
 
1490
}
 
1491
 
 
1492
int TableShare::parse_table_proto(Session& session, message::Table &table)
 
1493
{
 
1494
  int local_error= inner_parse_table_proto(session, table);
 
1495
 
 
1496
  if (not local_error)
 
1497
    return 0;
 
1498
 
 
1499
  error= local_error;
 
1500
  open_errno= errno;
 
1501
  errarg= 0;
 
1502
  hash_free(&name_hash);
 
1503
  open_table_error(local_error, open_errno, 0);
 
1504
 
 
1505
  return local_error;
 
1506
}
 
1507
 
 
1508
 
 
1509
/*
 
1510
  Read table definition from a binary / text based .frm cursor
 
1511
 
 
1512
  SYNOPSIS
 
1513
  open_table_def()
 
1514
  session               Thread Cursor
 
1515
  share         Fill this with table definition
 
1516
 
 
1517
  NOTES
 
1518
    This function is called when the table definition is not cached in
 
1519
    table_def_cache
 
1520
    The data is returned in 'share', which is alloced by
 
1521
    alloc_table_share().. The code assumes that share is initialized.
 
1522
 
 
1523
  RETURN VALUES
 
1524
   0    ok
 
1525
   1    Error (see open_table_error)
 
1526
   2    Error (see open_table_error)
 
1527
   3    Wrong data in .frm cursor
 
1528
   4    Error (see open_table_error)
 
1529
   5    Error (see open_table_error: charset unavailable)
 
1530
   6    Unknown .frm version
 
1531
*/
 
1532
 
 
1533
int TableShare::open_table_def(Session& session, TableIdentifier &identifier)
 
1534
{
 
1535
  int local_error;
 
1536
  bool error_given;
 
1537
 
 
1538
  local_error= 1;
 
1539
  error_given= 0;
 
1540
 
 
1541
  message::Table table;
 
1542
 
 
1543
  local_error= plugin::StorageEngine::getTableDefinition(session, identifier, table);
 
1544
 
 
1545
  if (local_error != EEXIST)
 
1546
  {
 
1547
    if (local_error > 0)
 
1548
    {
 
1549
      errno= local_error;
 
1550
      local_error= 1;
 
1551
    }
 
1552
    else
 
1553
    {
 
1554
      if (not table.IsInitialized())
 
1555
      {
 
1556
        local_error= 4;
 
1557
      }
 
1558
    }
 
1559
    goto err_not_open;
 
1560
  }
 
1561
 
 
1562
  local_error= parse_table_proto(session, table);
 
1563
 
 
1564
  setTableCategory(TABLE_CATEGORY_USER);
 
1565
 
 
1566
err_not_open:
 
1567
  if (local_error && !error_given)
 
1568
  {
 
1569
    error= local_error;
 
1570
    open_table_error(error, (open_errno= errno), 0);
 
1571
  }
 
1572
 
 
1573
  return(error);
 
1574
}
 
1575
 
 
1576
 
 
1577
/*
 
1578
  Open a table based on a TableShare
 
1579
 
 
1580
  SYNOPSIS
 
1581
    open_table_from_share()
 
1582
    session                     Thread Cursor
 
1583
    share               Table definition
 
1584
    alias               Alias for table
 
1585
    db_stat             open flags (for example HA_OPEN_KEYFILE|
 
1586
                        HA_OPEN_RNDFILE..) can be 0 (example in
 
1587
                        ha_example_table)
 
1588
    ha_open_flags       HA_OPEN_ABORT_IF_LOCKED etc..
 
1589
    outparam            result table
 
1590
 
 
1591
  RETURN VALUES
 
1592
   0    ok
 
1593
   1    Error (see open_table_error)
 
1594
   2    Error (see open_table_error)
 
1595
   3    Wrong data in .frm cursor
 
1596
   4    Error (see open_table_error)
 
1597
   5    Error (see open_table_error: charset unavailable)
 
1598
   7    Table definition has changed in engine
 
1599
*/
 
1600
 
 
1601
int TableShare::open_table_from_share(Session *session, const char *alias,
 
1602
                                      uint32_t db_stat, uint32_t ha_open_flags,
 
1603
                                      Table &outparam)
 
1604
{
 
1605
  int local_error;
 
1606
  uint32_t records, bitmap_size;
 
1607
  bool error_reported= false;
 
1608
  unsigned char *record, *bitmaps;
 
1609
  Field **field_ptr;
 
1610
 
 
1611
  /* Parsing of partitioning information from .frm needs session->lex set up. */
 
1612
  assert(session->lex->is_lex_started);
 
1613
 
 
1614
  local_error= 1;
 
1615
  outparam.resetTable(session, this, db_stat);
 
1616
 
 
1617
 
 
1618
  if (not (outparam.alias= strdup(alias)))
 
1619
    goto err;
 
1620
 
 
1621
  /* Allocate Cursor */
 
1622
  if (not (outparam.cursor= db_type()->getCursor(*this, &outparam.mem_root)))
 
1623
    goto err;
 
1624
 
 
1625
  local_error= 4;
 
1626
  records= 0;
 
1627
  if ((db_stat & HA_OPEN_KEYFILE))
 
1628
    records=1;
 
1629
 
 
1630
  records++;
 
1631
 
 
1632
  if (!(record= (unsigned char*) outparam.mem_root.alloc_root(rec_buff_length * records)))
 
1633
    goto err;
 
1634
 
 
1635
  if (records == 0)
 
1636
  {
 
1637
    /* We are probably in hard repair, and the buffers should not be used */
 
1638
    outparam.record[0]= outparam.record[1]= default_values;
 
1639
  }
 
1640
  else
 
1641
  {
 
1642
    outparam.record[0]= record;
 
1643
    if (records > 1)
 
1644
      outparam.record[1]= record+ rec_buff_length;
 
1645
    else
 
1646
      outparam.record[1]= outparam.record[0];   // Safety
 
1647
  }
 
1648
 
 
1649
#ifdef HAVE_purify
 
1650
  /*
 
1651
    We need this because when we read var-length rows, we are not updating
 
1652
    bytes after end of varchar
 
1653
  */
 
1654
  if (records > 1)
 
1655
  {
 
1656
    memcpy(outparam.record[0], default_values, rec_buff_length);
 
1657
    memcpy(outparam.record[1], default_values, null_bytes);
 
1658
    if (records > 2)
 
1659
      memcpy(outparam.record[1], default_values, rec_buff_length);
 
1660
  }
 
1661
#endif
 
1662
  if (records > 1)
 
1663
  {
 
1664
    memcpy(outparam.record[1], default_values, null_bytes);
 
1665
  }
 
1666
 
 
1667
  if (!(field_ptr = (Field **) outparam.mem_root.alloc_root( (uint32_t) ((fields+1)* sizeof(Field*)))))
 
1668
  {
 
1669
    goto err;
 
1670
  }
 
1671
 
 
1672
  outparam.field= field_ptr;
 
1673
 
 
1674
  record= (unsigned char*) outparam.record[0]-1;        /* Fieldstart = 1 */
 
1675
 
 
1676
  outparam.null_flags= (unsigned char*) record+1;
 
1677
 
 
1678
  /* Setup copy of fields from share, but use the right alias and record */
 
1679
  for (uint32_t i= 0 ; i < fields; i++, field_ptr++)
 
1680
  {
 
1681
    if (!((*field_ptr)= field[i]->clone(&outparam.mem_root, &outparam)))
 
1682
      goto err;
 
1683
  }
 
1684
  (*field_ptr)= 0;                              // End marker
 
1685
 
 
1686
  if (found_next_number_field)
 
1687
    outparam.found_next_number_field=
 
1688
      outparam.field[(uint32_t) (found_next_number_field - field)];
 
1689
  if (timestamp_field)
 
1690
    outparam.timestamp_field= (Field_timestamp*) outparam.field[timestamp_field_offset];
 
1691
 
 
1692
 
 
1693
  /* Fix key->name and key_part->field */
 
1694
  if (key_parts)
 
1695
  {
 
1696
    KEY *local_key_info, *key_info_end;
 
1697
    KEY_PART_INFO *key_part;
 
1698
    uint32_t n_length;
 
1699
    n_length= keys*sizeof(KEY) + key_parts*sizeof(KEY_PART_INFO);
 
1700
    if (!(local_key_info= (KEY*) outparam.mem_root.alloc_root(n_length)))
 
1701
      goto err;
 
1702
    outparam.key_info= local_key_info;
 
1703
    key_part= (reinterpret_cast<KEY_PART_INFO*> (local_key_info+keys));
 
1704
 
 
1705
    memcpy(local_key_info, key_info, sizeof(*local_key_info)*keys);
 
1706
    memcpy(key_part, key_info[0].key_part, (sizeof(*key_part) *
 
1707
                                                   key_parts));
 
1708
 
 
1709
    for (key_info_end= local_key_info + keys ;
 
1710
         local_key_info < key_info_end ;
 
1711
         local_key_info++)
 
1712
    {
 
1713
      KEY_PART_INFO *key_part_end;
 
1714
 
 
1715
      local_key_info->table= &outparam;
 
1716
      local_key_info->key_part= key_part;
 
1717
 
 
1718
      for (key_part_end= key_part+ local_key_info->key_parts ;
 
1719
           key_part < key_part_end ;
 
1720
           key_part++)
 
1721
      {
 
1722
        Field *local_field= key_part->field= outparam.field[key_part->fieldnr-1];
 
1723
 
 
1724
        if (local_field->key_length() != key_part->length &&
 
1725
            !(local_field->flags & BLOB_FLAG))
 
1726
        {
 
1727
          /*
 
1728
            We are using only a prefix of the column as a key:
 
1729
            Create a new field for the key part that matches the index
 
1730
          */
 
1731
          local_field= key_part->field= local_field->new_field(&outparam.mem_root, &outparam, 0);
 
1732
          local_field->field_length= key_part->length;
 
1733
        }
 
1734
      }
 
1735
    }
 
1736
  }
 
1737
 
 
1738
  /* Allocate bitmaps */
 
1739
 
 
1740
  bitmap_size= column_bitmap_size;
 
1741
  if (!(bitmaps= (unsigned char*) outparam.mem_root.alloc_root(bitmap_size*3)))
 
1742
  {
 
1743
    goto err;
 
1744
  }
 
1745
  outparam.def_read_set.init((my_bitmap_map*) bitmaps, fields);
 
1746
  outparam.def_write_set.init((my_bitmap_map*) (bitmaps+bitmap_size), fields);
 
1747
  outparam.tmp_set.init((my_bitmap_map*) (bitmaps+bitmap_size*2), fields);
 
1748
  outparam.default_column_bitmaps();
 
1749
 
 
1750
  /* The table struct is now initialized;  Open the table */
 
1751
  local_error= 2;
 
1752
  if (db_stat)
 
1753
  {
 
1754
    int ha_err;
 
1755
    if ((ha_err= (outparam.cursor->
 
1756
                  ha_open(&outparam, getNormalizedPath(),
 
1757
                          (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
 
1758
                          (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
 
1759
                           (db_stat & HA_WAIT_IF_LOCKED) ?  HA_OPEN_WAIT_IF_LOCKED :
 
1760
                           (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
 
1761
                           HA_OPEN_ABORT_IF_LOCKED :
 
1762
                           HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
 
1763
    {
 
1764
      switch (ha_err)
 
1765
      {
 
1766
        case HA_ERR_NO_SUCH_TABLE:
 
1767
          /*
 
1768
            The table did not exists in storage engine, use same error message
 
1769
            as if the .frm cursor didn't exist
 
1770
          */
 
1771
          local_error= 1;
 
1772
          errno= ENOENT;
 
1773
          break;
 
1774
        case EMFILE:
 
1775
          /*
 
1776
            Too many files opened, use same error message as if the .frm
 
1777
            cursor can't open
 
1778
           */
 
1779
          local_error= 1;
 
1780
          errno= EMFILE;
 
1781
          break;
 
1782
        default:
 
1783
          outparam.print_error(ha_err, MYF(0));
 
1784
          error_reported= true;
 
1785
          if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
 
1786
            local_error= 7;
 
1787
          break;
 
1788
      }
 
1789
      goto err;
 
1790
    }
 
1791
  }
 
1792
 
 
1793
#if defined(HAVE_purify)
 
1794
  memset(bitmaps, 0, bitmap_size*3);
 
1795
#endif
 
1796
 
 
1797
  return 0;
 
1798
 
 
1799
 err:
 
1800
  if (!error_reported)
 
1801
    open_table_error(local_error, errno, 0);
 
1802
 
 
1803
  delete outparam.cursor;
 
1804
  outparam.cursor= 0;                           // For easier error checking
 
1805
  outparam.db_stat= 0;
 
1806
  outparam.mem_root.free_root(MYF(0));       // Safe to call on zeroed root
 
1807
  free((char*) outparam.alias);
 
1808
  return (local_error);
 
1809
}
 
1810
 
 
1811
/* error message when opening a form cursor */
 
1812
void TableShare::open_table_error(int pass_error, int db_errno, int pass_errarg)
 
1813
{
 
1814
  int err_no;
 
1815
  char buff[FN_REFLEN];
 
1816
  myf errortype= ME_ERROR+ME_WAITTANG;
 
1817
 
 
1818
  switch (pass_error) {
 
1819
  case 7:
 
1820
  case 1:
 
1821
    if (db_errno == ENOENT)
 
1822
    {
 
1823
      my_error(ER_NO_SUCH_TABLE, MYF(0), db.str, table_name.str);
 
1824
    }
 
1825
    else
 
1826
    {
 
1827
      snprintf(buff, sizeof(buff), "%s",normalized_path.str);
 
1828
      my_error((db_errno == EMFILE) ? ER_CANT_OPEN_FILE : ER_FILE_NOT_FOUND,
 
1829
               errortype, buff, db_errno);
 
1830
    }
 
1831
    break;
 
1832
  case 2:
 
1833
  {
 
1834
    Cursor *cursor= 0;
 
1835
    const char *datext= "";
 
1836
 
 
1837
    if (db_type() != NULL)
 
1838
    {
 
1839
      if ((cursor= db_type()->getCursor(*this, current_session->mem_root)))
 
1840
      {
 
1841
        if (!(datext= *db_type()->bas_ext()))
 
1842
          datext= "";
 
1843
      }
 
1844
    }
 
1845
    err_no= (db_errno == ENOENT) ? ER_FILE_NOT_FOUND : (db_errno == EAGAIN) ?
 
1846
      ER_FILE_USED : ER_CANT_OPEN_FILE;
 
1847
    snprintf(buff, sizeof(buff), "%s%s", normalized_path.str,datext);
 
1848
    my_error(err_no,errortype, buff, db_errno);
 
1849
    delete cursor;
 
1850
    break;
 
1851
  }
 
1852
  case 5:
 
1853
  {
 
1854
    const char *csname= get_charset_name((uint32_t) pass_errarg);
 
1855
    char tmp[10];
 
1856
    if (!csname || csname[0] =='?')
 
1857
    {
 
1858
      snprintf(tmp, sizeof(tmp), "#%d", pass_errarg);
 
1859
      csname= tmp;
 
1860
    }
 
1861
    my_printf_error(ER_UNKNOWN_COLLATION,
 
1862
                    _("Unknown collation '%s' in table '%-.64s' definition"),
 
1863
                    MYF(0), csname, table_name.str);
 
1864
    break;
 
1865
  }
 
1866
  case 6:
 
1867
    snprintf(buff, sizeof(buff), "%s", normalized_path.str);
 
1868
    my_printf_error(ER_NOT_FORM_FILE,
 
1869
                    _("Table '%-.64s' was created with a different version "
 
1870
                    "of Drizzle and cannot be read"),
 
1871
                    MYF(0), buff);
 
1872
    break;
 
1873
  case 8:
 
1874
    break;
 
1875
  default:                              /* Better wrong error than none */
 
1876
  case 4:
 
1877
    snprintf(buff, sizeof(buff), "%s", normalized_path.str);
 
1878
    my_error(ER_NOT_FORM_FILE, errortype, buff, 0);
 
1879
    break;
 
1880
  }
 
1881
  return;
 
1882
} /* open_table_error */
 
1883
 
 
1884
 
421
1885
} /* namespace drizzled */