42
32
#include <drizzled/field/double.h>
43
33
#include <drizzled/unireg.h>
44
34
#include <drizzled/message/table.pb.h>
45
#include "drizzled/sql_table.h"
46
#include "drizzled/charset.h"
47
#include "drizzled/internal/m_string.h"
48
#include "plugin/myisam/myisam.h"
50
36
#include <drizzled/item/string.h>
51
37
#include <drizzled/item/int.h>
52
38
#include <drizzled/item/decimal.h>
53
39
#include <drizzled/item/float.h>
54
40
#include <drizzled/item/null.h>
55
#include <drizzled/temporal.h>
57
#include "drizzled/table/instance.h"
59
#include "drizzled/table_proto.h"
42
#include <drizzled/table_proto.h>
61
49
using namespace std;
66
extern pid_t current_pid;
67
extern plugin::StorageEngine *heap_engine;
68
extern plugin::StorageEngine *myisam_engine;
70
/* Functions defined in this cursor */
50
using namespace drizzled;
52
/* Functions defined in this file */
72
54
void open_table_error(TableShare *share, int error, int db_errno,
73
55
myf errortype, int errarg);
75
57
/*************************************************************************/
77
// @note this should all be the destructor
78
int Table::delete_table(bool free_share)
59
/* Get column name from column hash */
61
static unsigned char *get_field_name(Field **buff, size_t *length, bool)
63
*length= (uint32_t) strlen((*buff)->field_name);
64
return (unsigned char*) (*buff)->field_name;
69
Returns pointer to '.frm' extension of the file name.
76
Checks file name part starting with the rightmost '.' character,
77
and returns it if it is equal to '.dfe'.
80
It is a good idea to get rid of this function modifying the code
81
to garantee that the functions presently calling fn_rext() always
82
get arguments in the same format: either with '.frm' or without '.frm'.
85
Pointer to the '.frm' extension. If there is no extension,
86
or extension is not '.frm', pointer at the end of file name.
89
char *fn_rext(char *name)
91
char *res= strrchr(name, '.');
92
if (res && !strcmp(res, ".dfe"))
94
return name + strlen(name);
97
static TABLE_CATEGORY get_table_category(const LEX_STRING *db)
101
if ((db->length == INFORMATION_SCHEMA_NAME.length()) &&
102
(my_strcasecmp(system_charset_info,
103
INFORMATION_SCHEMA_NAME.c_str(),
106
return TABLE_CATEGORY_INFORMATION;
109
return TABLE_CATEGORY_USER;
114
Allocate a setup TableShare structure
118
TableList Take database and table name from there
119
key Table cache key (db \0 table_name \0...)
120
key_length Length of key
123
0 Error (out of memory)
127
TableShare *alloc_table_share(TableList *table_list, char *key,
132
char *key_buff, *path_buff;
133
char path[FN_REFLEN];
134
uint32_t path_length;
136
path_length= build_table_filename(path, sizeof(path) - 1,
138
table_list->table_name, false);
139
init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
140
if (multi_alloc_root(&mem_root,
141
&share, sizeof(*share),
142
&key_buff, key_length,
143
&path_buff, path_length + 1,
146
memset(share, 0, sizeof(*share));
148
share->set_table_cache_key(key_buff, key, key_length);
150
share->path.str= path_buff;
151
share->path.length= path_length;
152
strcpy(share->path.str, path);
153
share->normalized_path.str= share->path.str;
154
share->normalized_path.length= path_length;
156
share->version= refresh_version;
158
memcpy(&share->mem_root, &mem_root, sizeof(mem_root));
159
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
160
pthread_cond_init(&share->cond, NULL);
166
static enum_field_types proto_field_type_to_drizzle_type(uint32_t proto_field_type)
168
enum_field_types field_type;
170
switch(proto_field_type)
172
case message::Table::Field::TINYINT:
173
field_type= DRIZZLE_TYPE_TINY;
175
case message::Table::Field::INTEGER:
176
field_type= DRIZZLE_TYPE_LONG;
178
case message::Table::Field::DOUBLE:
179
field_type= DRIZZLE_TYPE_DOUBLE;
181
case message::Table::Field::TIMESTAMP:
182
field_type= DRIZZLE_TYPE_TIMESTAMP;
184
case message::Table::Field::BIGINT:
185
field_type= DRIZZLE_TYPE_LONGLONG;
187
case message::Table::Field::DATETIME:
188
field_type= DRIZZLE_TYPE_DATETIME;
190
case message::Table::Field::DATE:
191
field_type= DRIZZLE_TYPE_DATE;
193
case message::Table::Field::VARCHAR:
194
field_type= DRIZZLE_TYPE_VARCHAR;
196
case message::Table::Field::DECIMAL:
197
field_type= DRIZZLE_TYPE_NEWDECIMAL;
199
case message::Table::Field::ENUM:
200
field_type= DRIZZLE_TYPE_ENUM;
202
case message::Table::Field::BLOB:
203
field_type= DRIZZLE_TYPE_BLOB;
206
field_type= DRIZZLE_TYPE_TINY; /* Set value to kill GCC warning */
213
static Item *default_value_item(enum_field_types field_type,
214
const CHARSET_INFO *charset,
215
bool default_null, const string *default_value,
216
const string *default_bin_value)
218
Item *default_item= NULL;
223
return new Item_null();
228
case DRIZZLE_TYPE_TINY:
229
case DRIZZLE_TYPE_LONG:
230
case DRIZZLE_TYPE_LONGLONG:
231
default_item= new Item_int(default_value->c_str(),
232
(int64_t) my_strtoll10(default_value->c_str(),
235
default_value->length());
237
case DRIZZLE_TYPE_DOUBLE:
238
default_item= new Item_float(default_value->c_str(),
239
default_value->length());
241
case DRIZZLE_TYPE_NULL:
243
case DRIZZLE_TYPE_TIMESTAMP:
244
case DRIZZLE_TYPE_DATETIME:
245
case DRIZZLE_TYPE_DATE:
246
if (default_value->compare("NOW()") == 0)
248
case DRIZZLE_TYPE_ENUM:
249
default_item= new Item_string(default_value->c_str(),
250
default_value->length(),
251
system_charset_info);
253
case DRIZZLE_TYPE_VARCHAR:
254
case DRIZZLE_TYPE_BLOB: /* Blob is here due to TINYTEXT. Feel the hate. */
255
if (charset==&my_charset_bin)
257
default_item= new Item_string(default_bin_value->c_str(),
258
default_bin_value->length(),
263
default_item= new Item_string(default_value->c_str(),
264
default_value->length(),
265
system_charset_info);
268
case DRIZZLE_TYPE_NEWDECIMAL:
269
default_item= new Item_decimal(default_value->c_str(),
270
default_value->length(),
271
system_charset_info);
278
int parse_table_proto(Session *session,
279
message::Table &table,
283
handler *handler_file= NULL;
285
share->setTableProto(new(std::nothrow) message::Table(table));
287
share->storage_engine= plugin::StorageEngine::findByName(session, table.engine().name());
289
message::Table::TableOptions table_options;
291
if (table.has_options())
292
table_options= table.options();
294
uint32_t db_create_options= 0;
296
if (table_options.has_pack_keys())
298
if (table_options.pack_keys())
299
db_create_options|= HA_OPTION_PACK_KEYS;
301
db_create_options|= HA_OPTION_NO_PACK_KEYS;
304
if (table_options.pack_record())
305
db_create_options|= HA_OPTION_PACK_RECORD;
307
/* db_create_options was stored as 2 bytes in FRM
308
Any HA_OPTION_ that doesn't fit into 2 bytes was silently truncated away.
310
share->db_create_options= (db_create_options & 0x0000FFFF);
311
share->db_options_in_use= share->db_create_options;
313
share->row_type= table_options.has_row_type() ?
314
(enum row_type) table_options.row_type() : ROW_TYPE_DEFAULT;
316
share->block_size= table_options.has_block_size() ?
317
table_options.block_size() : 0;
319
share->table_charset= get_charset(table_options.has_collation_id()?
320
table_options.collation_id() : 0);
322
if (!share->table_charset)
324
/* unknown charset in head[38] or pre-3.23 frm */
325
if (use_mb(default_charset_info))
327
/* Warn that we may be changing the size of character columns */
328
errmsg_printf(ERRMSG_LVL_WARN,
329
_("'%s' had no or invalid character set, "
330
"and default character set is multi-byte, "
331
"so character column sizes may have changed"),
334
share->table_charset= default_charset_info;
337
share->db_record_offset= 1;
339
share->blob_ptr_size= portable_sizeof_char_ptr; // more bonghits.
341
share->db_low_byte_first= true;
343
share->keys= table.indexes_size();
346
for (int indx= 0; indx < table.indexes_size(); indx++)
347
share->key_parts+= table.indexes(indx).index_part_size();
349
share->key_info= (KEY*) alloc_root(&share->mem_root,
350
table.indexes_size() * sizeof(KEY)
351
+share->key_parts*sizeof(KEY_PART_INFO));
353
KEY_PART_INFO *key_part;
355
key_part= reinterpret_cast<KEY_PART_INFO*>
356
(share->key_info+table.indexes_size());
359
ulong *rec_per_key= (ulong*) alloc_root(&share->mem_root,
360
sizeof(ulong*)*share->key_parts);
362
share->keynames.count= table.indexes_size();
363
share->keynames.name= NULL;
364
share->keynames.type_names= (const char**)
365
alloc_root(&share->mem_root, sizeof(char*) * (table.indexes_size()+1));
367
share->keynames.type_lengths= (unsigned int*)
368
alloc_root(&share->mem_root,
369
sizeof(unsigned int) * (table.indexes_size()+1));
371
share->keynames.type_names[share->keynames.count]= NULL;
372
share->keynames.type_lengths[share->keynames.count]= 0;
374
KEY* keyinfo= share->key_info;
375
for (int keynr= 0; keynr < table.indexes_size(); keynr++, keyinfo++)
377
message::Table::Index indx= table.indexes(keynr);
382
if (indx.is_unique())
383
keyinfo->flags|= HA_NOSAME;
385
if (indx.has_options())
387
message::Table::Index::IndexOptions indx_options= indx.options();
388
if (indx_options.pack_key())
389
keyinfo->flags|= HA_PACK_KEY;
391
if (indx_options.var_length_key())
392
keyinfo->flags|= HA_VAR_LENGTH_PART;
394
if (indx_options.null_part_key())
395
keyinfo->flags|= HA_NULL_PART_KEY;
397
if (indx_options.binary_pack_key())
398
keyinfo->flags|= HA_BINARY_PACK_KEY;
400
if (indx_options.has_partial_segments())
401
keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
403
if (indx_options.auto_generated_key())
404
keyinfo->flags|= HA_GENERATED_KEY;
406
if (indx_options.has_key_block_size())
408
keyinfo->flags|= HA_USES_BLOCK_SIZE;
409
keyinfo->block_size= indx_options.key_block_size();
413
keyinfo->block_size= 0;
420
case message::Table::Index::UNKNOWN_INDEX:
421
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
423
case message::Table::Index::BTREE:
424
keyinfo->algorithm= HA_KEY_ALG_BTREE;
426
case message::Table::Index::RTREE:
427
keyinfo->algorithm= HA_KEY_ALG_RTREE;
429
case message::Table::Index::HASH:
430
keyinfo->algorithm= HA_KEY_ALG_HASH;
432
case message::Table::Index::FULLTEXT:
433
keyinfo->algorithm= HA_KEY_ALG_FULLTEXT;
436
/* TODO: suitable warning ? */
437
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
441
keyinfo->key_length= indx.key_length();
443
keyinfo->key_parts= indx.index_part_size();
445
keyinfo->key_part= key_part;
446
keyinfo->rec_per_key= rec_per_key;
448
for (unsigned int partnr= 0;
449
partnr < keyinfo->key_parts;
450
partnr++, key_part++)
452
message::Table::Index::IndexPart part;
453
part= indx.index_part(partnr);
457
key_part->field= NULL;
458
key_part->fieldnr= part.fieldnr() + 1; // start from 1.
459
key_part->null_bit= 0;
460
/* key_part->null_offset is only set if null_bit (see later) */
461
/* key_part->key_type= */ /* I *THINK* this may be okay.... */
462
/* key_part->type ???? */
463
key_part->key_part_flag= 0;
464
if (part.has_in_reverse_order())
465
key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
467
key_part->length= part.compare_length();
469
key_part->store_length= key_part->length;
471
/* key_part->offset is set later */
472
key_part->key_type= part.key_type();
476
if (!indx.has_comment())
478
keyinfo->comment.length= 0;
479
keyinfo->comment.str= NULL;
483
keyinfo->flags|= HA_USES_COMMENT;
484
keyinfo->comment.length= indx.comment().length();
485
keyinfo->comment.str= strmake_root(&share->mem_root,
486
indx.comment().c_str(),
487
keyinfo->comment.length);
490
keyinfo->name= strmake_root(&share->mem_root,
492
indx.name().length());
494
share->keynames.type_names[keynr]= keyinfo->name;
495
share->keynames.type_lengths[keynr]= indx.name().length();
498
share->keys_for_keyread.reset();
499
set_prefix(share->keys_in_use, share->keys);
501
if (table_options.has_connect_string())
503
size_t len= table_options.connect_string().length();
504
const char* str= table_options.connect_string().c_str();
506
share->connect_string.length= len;
507
share->connect_string.str= strmake_root(&share->mem_root, str, len);
510
share->key_block_size= table_options.has_key_block_size() ?
511
table_options.key_block_size() : 0;
513
share->fields= table.field_size();
515
share->field= (Field**) alloc_root(&share->mem_root,
516
((share->fields+1) * sizeof(Field*)));
517
share->field[share->fields]= NULL;
519
uint32_t null_fields= 0;
522
uint32_t *field_offsets= (uint32_t*)malloc(share->fields * sizeof(uint32_t));
523
uint32_t *field_pack_length=(uint32_t*)malloc(share->fields*sizeof(uint32_t));
525
assert(field_offsets && field_pack_length); // TODO: fixme
527
uint32_t interval_count= 0;
528
uint32_t interval_parts= 0;
530
uint32_t stored_columns_reclength= 0;
532
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
534
message::Table::Field pfield= table.field(fieldnr);
535
if (pfield.has_constraints() && pfield.constraints().is_nullable())
538
enum_field_types drizzle_field_type=
539
proto_field_type_to_drizzle_type(pfield.type());
541
field_offsets[fieldnr]= stored_columns_reclength;
543
/* the below switch is very similar to
544
CreateField::create_length_to_internal_length in field.cc
545
(which should one day be replace by just this code)
547
switch(drizzle_field_type)
549
case DRIZZLE_TYPE_BLOB:
550
case DRIZZLE_TYPE_VARCHAR:
552
message::Table::Field::StringFieldOptions field_options=
553
pfield.string_options();
555
const CHARSET_INFO *cs= get_charset(field_options.has_collation_id()?
556
field_options.collation_id() : 0);
559
cs= default_charset_info;
561
field_pack_length[fieldnr]=
562
calc_pack_length(drizzle_field_type,
563
field_options.length() * cs->mbmaxlen);
567
case DRIZZLE_TYPE_ENUM:
569
message::Table::Field::SetFieldOptions field_options=
570
pfield.set_options();
572
field_pack_length[fieldnr]=
573
get_enum_pack_length(field_options.field_value_size());
576
interval_parts+= field_options.field_value_size();
579
case DRIZZLE_TYPE_NEWDECIMAL:
581
message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
582
field_pack_length[fieldnr]=
583
my_decimal_get_binary_size(fo.precision(), fo.scale());
587
/* Zero is okay here as length is fixed for other types. */
588
field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
591
share->reclength+= field_pack_length[fieldnr];
592
stored_columns_reclength+= field_pack_length[fieldnr];
596
/* data_offset added to stored_rec_length later */
597
share->stored_rec_length= stored_columns_reclength;
599
share->null_fields= null_fields;
601
ulong null_bits= null_fields;
602
if (!table_options.pack_record())
604
ulong data_offset= (null_bits + 7)/8;
607
share->reclength+= data_offset;
608
share->stored_rec_length+= data_offset;
610
ulong rec_buff_length;
612
rec_buff_length= ALIGN_SIZE(share->reclength + 1);
613
share->rec_buff_length= rec_buff_length;
615
unsigned char* record= NULL;
617
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
621
memset(record, 0, rec_buff_length);
625
if (!table_options.pack_record())
627
null_count++; // one bit for delete mark.
631
share->default_values= record;
635
share->intervals= (TYPELIB*)alloc_root(&share->mem_root,
636
interval_count*sizeof(TYPELIB));
639
share->intervals= NULL;
641
share->fieldnames.type_names= (const char**)alloc_root(&share->mem_root,
642
(share->fields+1)*sizeof(char*));
644
share->fieldnames.type_lengths= (unsigned int*) alloc_root(&share->mem_root,
645
(share->fields+1)*sizeof(unsigned int));
647
share->fieldnames.type_names[share->fields]= NULL;
648
share->fieldnames.type_lengths[share->fields]= 0;
649
share->fieldnames.count= share->fields;
652
/* Now fix the TYPELIBs for the intervals (enum values)
656
uint32_t interval_nr= 0;
658
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
660
message::Table::Field pfield= table.field(fieldnr);
663
share->fieldnames.type_names[fieldnr]= strmake_root(&share->mem_root,
664
pfield.name().c_str(),
665
pfield.name().length());
667
share->fieldnames.type_lengths[fieldnr]= pfield.name().length();
670
if (pfield.type() != message::Table::Field::ENUM)
673
message::Table::Field::SetFieldOptions field_options= pfield.set_options();
675
const CHARSET_INFO *charset= get_charset(field_options.has_collation_id()?
676
field_options.collation_id() : 0);
679
charset= default_charset_info;
681
TYPELIB *t= &(share->intervals[interval_nr]);
683
t->type_names= (const char**)alloc_root(&share->mem_root,
684
(field_options.field_value_size()+1)*sizeof(char*));
686
t->type_lengths= (unsigned int*) alloc_root(&share->mem_root,
687
(field_options.field_value_size()+1)*sizeof(unsigned int));
689
t->type_names[field_options.field_value_size()]= NULL;
690
t->type_lengths[field_options.field_value_size()]= 0;
692
t->count= field_options.field_value_size();
695
for (int n= 0; n < field_options.field_value_size(); n++)
697
t->type_names[n]= strmake_root(&share->mem_root,
698
field_options.field_value(n).c_str(),
699
field_options.field_value(n).length());
701
/* Go ask the charset what the length is as for "" length=1
702
and there's stripping spaces or some other crack going on.
705
lengthsp= charset->cset->lengthsp(charset, t->type_names[n],
706
field_options.field_value(n).length());
707
t->type_lengths[n]= lengthsp;
713
/* and read the fields */
716
bool use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
719
use_hash= !hash_init(&share->name_hash,
722
(hash_get_key) get_field_name, 0, 0);
724
unsigned char* null_pos= record;;
725
int null_bit_pos= (table_options.pack_record()) ? 0 : 1;
727
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
729
message::Table::Field pfield= table.field(fieldnr);
731
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
733
switch(pfield.format())
735
case message::Table::Field::DefaultFormat:
736
column_format= COLUMN_FORMAT_TYPE_DEFAULT;
738
case message::Table::Field::FixedFormat:
739
column_format= COLUMN_FORMAT_TYPE_FIXED;
741
case message::Table::Field::DynamicFormat:
742
column_format= COLUMN_FORMAT_TYPE_DYNAMIC;
748
Field::utype unireg_type= Field::NONE;
750
if (pfield.has_numeric_options()
751
&& pfield.numeric_options().is_autoincrement())
753
unireg_type= Field::NEXT_NUMBER;
756
if (pfield.has_options()
757
&& pfield.options().has_default_value()
758
&& pfield.options().default_value().compare("NOW()") == 0)
760
if (pfield.options().has_update_value()
761
&& pfield.options().update_value().compare("NOW()") == 0)
763
unireg_type= Field::TIMESTAMP_DNUN_FIELD;
765
else if (!pfield.options().has_update_value())
767
unireg_type= Field::TIMESTAMP_DN_FIELD;
770
assert(1); // Invalid update value.
772
else if (pfield.has_options()
773
&& pfield.options().has_update_value()
774
&& pfield.options().update_value().compare("NOW()") == 0)
776
unireg_type= Field::TIMESTAMP_UN_FIELD;
780
if (!pfield.has_comment())
782
comment.str= (char*)"";
787
size_t len= pfield.comment().length();
788
const char* str= pfield.comment().c_str();
790
comment.str= strmake_root(&share->mem_root, str, len);
794
enum_field_types field_type;
796
field_type= proto_field_type_to_drizzle_type(pfield.type());
798
const CHARSET_INFO *charset= &my_charset_bin;
800
if (field_type==DRIZZLE_TYPE_BLOB
801
|| field_type==DRIZZLE_TYPE_VARCHAR)
803
message::Table::Field::StringFieldOptions field_options=
804
pfield.string_options();
806
charset= get_charset(field_options.has_collation_id()?
807
field_options.collation_id() : 0);
810
charset= default_charset_info;
814
if (field_type==DRIZZLE_TYPE_ENUM)
816
message::Table::Field::SetFieldOptions field_options=
817
pfield.set_options();
819
charset= get_charset(field_options.has_collation_id()?
820
field_options.collation_id() : 0);
823
charset= default_charset_info;
827
Item *default_value= NULL;
829
if (pfield.options().has_default_value()
830
|| pfield.options().has_default_null()
831
|| pfield.options().has_default_bin_value())
833
default_value= default_value_item(field_type,
835
pfield.options().default_null(),
836
&pfield.options().default_value(),
837
&pfield.options().default_bin_value());
840
uint32_t pack_flag= pfield.pack_flag(); /* TODO: MUST DIE */
842
Table temp_table; /* Use this so that BLOB DEFAULT '' works */
843
memset(&temp_table, 0, sizeof(temp_table));
845
temp_table.in_use= session;
846
temp_table.s->db_low_byte_first= 1; //handler->low_byte_first();
847
temp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
849
Field* f= make_field(share, &share->mem_root,
850
record+field_offsets[fieldnr]+data_offset,
851
pfield.options().length(),
857
(Field::utype) MTYP_TYPENR(unireg_type),
858
((field_type==DRIZZLE_TYPE_ENUM)?
859
share->intervals+(interval_nr++)
861
share->fieldnames.type_names[fieldnr]);
863
share->field[fieldnr]= f;
865
f->init(&temp_table); /* blob default values need table obj */
867
if (!(f->flags & NOT_NULL_FLAG))
869
*f->null_ptr|= f->null_bit;
870
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
877
enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
878
session->count_cuted_fields= CHECK_FIELD_WARN;
879
int res= default_value->save_in_field(f, 1);
880
session->count_cuted_fields= old_count_cuted_fields;
881
if (res != 0 && res != 3)
883
my_error(ER_INVALID_DEFAULT, MYF(0), f->field_name);
888
else if (f->real_type() == DRIZZLE_TYPE_ENUM &&
889
(f->flags & NOT_NULL_FLAG))
892
f->store((int64_t) 1, true);
897
/* hack to undo f->init() */
901
f->field_index= fieldnr;
904
&& !(f->unireg_check==Field::NEXT_NUMBER)
905
&& (f->flags & NOT_NULL_FLAG)
906
&& (f->real_type() != DRIZZLE_TYPE_TIMESTAMP))
907
f->flags|= NO_DEFAULT_VALUE_FLAG;
909
if (f->unireg_check == Field::NEXT_NUMBER)
910
share->found_next_number_field= &(share->field[fieldnr]);
912
if (share->timestamp_field == f)
913
share->timestamp_field_offset= fieldnr;
915
if (use_hash) /* supposedly this never fails... but comments lie */
916
(void) my_hash_insert(&share->name_hash,
917
(unsigned char*)&(share->field[fieldnr]));
921
keyinfo= share->key_info;
922
for (unsigned int keynr= 0; keynr < share->keys; keynr++, keyinfo++)
924
key_part= keyinfo->key_part;
926
for (unsigned int partnr= 0;
927
partnr < keyinfo->key_parts;
928
partnr++, key_part++)
930
/* Fix up key_part->offset by adding data_offset.
931
We really should compute offset as well.
932
But at least this way we are a little better. */
933
key_part->offset= field_offsets[key_part->fieldnr-1] + data_offset;
938
We need to set the unused bits to 1. If the number of bits is a multiple
939
of 8 there are no unused bits.
943
*(record + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
945
share->null_bytes= (null_pos - (unsigned char*) record +
946
(null_bit_pos + 7) / 8);
948
share->last_null_bit_pos= null_bit_pos;
951
free(field_pack_length);
953
if (!(handler_file= get_new_handler(share, session->mem_root,
958
if (share->key_parts)
960
uint32_t primary_key=(uint32_t) (find_type((char*) "PRIMARY",
961
&share->keynames, 3) - 1);
963
int64_t ha_option= handler_file->ha_table_flags();
965
keyinfo= share->key_info;
966
key_part= keyinfo->key_part;
968
for (uint32_t key= 0 ; key < share->keys ; key++,keyinfo++)
970
uint32_t usable_parts= 0;
972
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
975
If the UNIQUE key doesn't have NULL columns and is not a part key
976
declare this as a primary key.
979
for (uint32_t i= 0 ; i < keyinfo->key_parts ;i++)
981
uint32_t fieldnr= key_part[i].fieldnr;
983
share->field[fieldnr-1]->null_ptr ||
984
share->field[fieldnr-1]->key_length() !=
987
primary_key=MAX_KEY; // Can't be used
993
for (uint32_t i= 0 ; i < keyinfo->key_parts ; key_part++,i++)
996
if (!key_part->fieldnr)
998
// error= 4; // Wrong file
999
abort(); // goto err;
1001
field= key_part->field= share->field[key_part->fieldnr-1];
1002
key_part->type= field->key_type();
1003
if (field->null_ptr)
1005
key_part->null_offset=(uint32_t) ((unsigned char*) field->null_ptr -
1006
share->default_values);
1007
key_part->null_bit= field->null_bit;
1008
key_part->store_length+=HA_KEY_NULL_LENGTH;
1009
keyinfo->flags|=HA_NULL_PART_KEY;
1010
keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
1011
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
1013
if (field->type() == DRIZZLE_TYPE_BLOB ||
1014
field->real_type() == DRIZZLE_TYPE_VARCHAR)
1016
if (field->type() == DRIZZLE_TYPE_BLOB)
1017
key_part->key_part_flag|= HA_BLOB_PART;
1019
key_part->key_part_flag|= HA_VAR_LENGTH_PART;
1020
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
1021
key_part->store_length+=HA_KEY_BLOB_LENGTH;
1022
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
1024
if (i == 0 && key != primary_key)
1025
field->flags |= (((keyinfo->flags & HA_NOSAME) &&
1026
(keyinfo->key_parts == 1)) ?
1027
UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
1029
field->key_start.set(key);
1030
if (field->key_length() == key_part->length &&
1031
!(field->flags & BLOB_FLAG))
1033
if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
1035
share->keys_for_keyread.set(key);
1036
field->part_of_key.set(key);
1037
field->part_of_key_not_clustered.set(key);
1039
if (handler_file->index_flags(key, i, 1) & HA_READ_ORDER)
1040
field->part_of_sortkey.set(key);
1042
if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
1044
usable_parts++; // For FILESORT
1045
field->flags|= PART_KEY_FLAG;
1046
if (key == primary_key)
1048
field->flags|= PRI_KEY_FLAG;
1050
If this field is part of the primary key and all keys contains
1051
the primary key, then we can use any key to find this column
1053
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
1055
field->part_of_key= share->keys_in_use;
1056
if (field->part_of_sortkey.test(key))
1057
field->part_of_sortkey= share->keys_in_use;
1060
if (field->key_length() != key_part->length)
1062
key_part->key_part_flag|= HA_PART_KEY_SEG;
1065
keyinfo->usable_key_parts= usable_parts; // Filesort
1067
set_if_bigger(share->max_key_length,keyinfo->key_length+
1068
keyinfo->key_parts);
1069
share->total_key_length+= keyinfo->key_length;
1071
MERGE tables do not have unique indexes. But every key could be
1072
an unique index on the underlying MyISAM table. (Bug #10400)
1074
if ((keyinfo->flags & HA_NOSAME) ||
1075
(ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
1076
set_if_bigger(share->max_unique_length,keyinfo->key_length);
1078
if (primary_key < MAX_KEY &&
1079
(share->keys_in_use.test(primary_key)))
1081
share->primary_key= primary_key;
1083
If we are using an integer as the primary key then allow the user to
1084
refer to it as '_rowid'
1086
if (share->key_info[primary_key].key_parts == 1)
1088
Field *field= share->key_info[primary_key].key_part[0].field;
1089
if (field && field->result_type() == INT_RESULT)
1091
/* note that fieldnr here (and rowid_field_offset) starts from 1 */
1092
share->rowid_field_offset= (share->key_info[primary_key].key_part[0].
1099
share->primary_key = MAX_KEY; // we do not have a primary key
1102
share->primary_key= MAX_KEY;
1104
if (share->found_next_number_field)
1106
Field *reg_field= *share->found_next_number_field;
1107
if ((int) (share->next_number_index= (uint32_t)
1108
find_ref_key(share->key_info, share->keys,
1109
share->default_values, reg_field,
1110
&share->next_number_key_offset,
1111
&share->next_number_keypart)) < 0)
1113
/* Wrong field definition */
1118
reg_field->flags |= AUTO_INCREMENT_FLAG;
1121
if (share->blob_fields)
1126
/* Store offsets to blob fields to find them fast */
1127
if (!(share->blob_field= save=
1128
(uint*) alloc_root(&share->mem_root,
1129
(uint32_t) (share->blob_fields* sizeof(uint32_t)))))
1131
for (k= 0, ptr= share->field ; *ptr ; ptr++, k++)
1133
if ((*ptr)->flags & BLOB_FLAG)
1138
share->db_low_byte_first= handler_file->low_byte_first();
1139
share->column_bitmap_size= bitmap_buffer_size(share->fields);
1141
my_bitmap_map *bitmaps;
1143
if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1144
share->column_bitmap_size)))
1146
share->all_set.init(bitmaps, share->fields);
1147
share->all_set.setAll();
1150
delete handler_file;
1154
share->error= error;
1155
share->open_errno= my_errno;
1157
hash_free(&share->name_hash);
1159
delete handler_file;
1160
share->open_table_error(error, share->open_errno, 0);
1166
Read table definition from a binary / text based .frm file
1170
session Thread handler
1171
share Fill this with table definition
1174
This function is called when the table definition is not cached in
1176
The data is returned in 'share', which is alloced by
1177
alloc_table_share().. The code assumes that share is initialized.
1181
1 Error (see open_table_error)
1182
2 Error (see open_table_error)
1183
3 Wrong data in .frm file
1184
4 Error (see open_table_error)
1185
5 Error (see open_table_error: charset unavailable)
1186
6 Unknown .frm version
1189
int open_table_def(Session *session, TableShare *share)
1197
message::Table table;
1199
error= plugin::StorageEngine::getTableProto(share->normalized_path.str,
1202
if (error != EEXIST)
1211
if (!table.IsInitialized())
1219
error= parse_table_proto(session, table, share);
1221
share->table_category= get_table_category(& share->db);
1224
session->status_var.opened_shares++;
1227
if (error && !error_given)
1229
share->error= error;
1230
share->open_table_error(error, (share->open_errno= my_errno), 0);
1238
Open a table based on a TableShare
1241
open_table_from_share()
1242
session Thread handler
1243
share Table definition
1244
alias Alias for table
1245
db_stat open flags (for example HA_OPEN_KEYFILE|
1246
HA_OPEN_RNDFILE..) can be 0 (example in
1248
prgflag READ_ALL etc..
1249
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
1250
outparam result table
1251
open_mode One of OTM_OPEN|OTM_CREATE|OTM_ALTER
1252
if OTM_CREATE some errors are ignore
1253
if OTM_ALTER HA_OPEN is not called
1257
1 Error (see open_table_error)
1258
2 Error (see open_table_error)
1259
3 Wrong data in .frm file
1260
4 Error (see open_table_error)
1261
5 Error (see open_table_error: charset unavailable)
1262
7 Table definition has changed in engine
1265
int open_table_from_share(Session *session, TableShare *share, const char *alias,
1266
uint32_t db_stat, uint32_t prgflag, uint32_t ha_open_flags,
1267
Table *outparam, open_table_mode open_mode)
1270
uint32_t records, i, bitmap_size;
1271
bool error_reported= false;
1272
unsigned char *record, *bitmaps;
1275
/* Parsing of partitioning information from .frm needs session->lex set up. */
1276
assert(session->lex->is_lex_started);
1279
outparam->resetTable(session, share, db_stat);
1282
if (!(outparam->alias= strdup(alias)))
1285
/* Allocate handler */
1286
if (!(prgflag & OPEN_FRM_FILE_ONLY))
1288
if (!(outparam->file= get_new_handler(share, &outparam->mem_root,
1299
if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
1301
if (prgflag & (READ_ALL+EXTRA_RECORD))
1304
if (!(record= (unsigned char*) alloc_root(&outparam->mem_root,
1305
share->rec_buff_length * records)))
1310
/* We are probably in hard repair, and the buffers should not be used */
1311
outparam->record[0]= outparam->record[1]= share->default_values;
1315
outparam->record[0]= record;
1317
outparam->record[1]= record+ share->rec_buff_length;
1319
outparam->record[1]= outparam->record[0]; // Safety
1324
We need this because when we read var-length rows, we are not updating
1325
bytes after end of varchar
1329
memcpy(outparam->record[0], share->default_values, share->rec_buff_length);
1330
memcpy(outparam->record[1], share->default_values, share->null_bytes);
1332
memcpy(outparam->record[1], share->default_values,
1333
share->rec_buff_length);
1337
if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root,
1338
(uint32_t) ((share->fields+1)*
1342
outparam->field= field_ptr;
1344
record= (unsigned char*) outparam->record[0]-1; /* Fieldstart = 1 */
1346
outparam->null_flags= (unsigned char*) record+1;
1348
/* Setup copy of fields from share, but use the right alias and record */
1349
for (i= 0 ; i < share->fields; i++, field_ptr++)
1351
if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam)))
1354
(*field_ptr)= 0; // End marker
1356
if (share->found_next_number_field)
1357
outparam->found_next_number_field=
1358
outparam->field[(uint32_t) (share->found_next_number_field - share->field)];
1359
if (share->timestamp_field)
1360
outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
1363
/* Fix key->name and key_part->field */
1364
if (share->key_parts)
1366
KEY *key_info, *key_info_end;
1367
KEY_PART_INFO *key_part;
1369
n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO);
1370
if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length)))
1372
outparam->key_info= key_info;
1373
key_part= (reinterpret_cast<KEY_PART_INFO*> (key_info+share->keys));
1375
memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
1376
memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) *
1379
for (key_info_end= key_info + share->keys ;
1380
key_info < key_info_end ;
1383
KEY_PART_INFO *key_part_end;
1385
key_info->table= outparam;
1386
key_info->key_part= key_part;
1388
for (key_part_end= key_part+ key_info->key_parts ;
1389
key_part < key_part_end ;
1392
Field *field= key_part->field= outparam->field[key_part->fieldnr-1];
1394
if (field->key_length() != key_part->length &&
1395
!(field->flags & BLOB_FLAG))
1398
We are using only a prefix of the column as a key:
1399
Create a new field for the key part that matches the index
1401
field= key_part->field=field->new_field(&outparam->mem_root,
1403
field->field_length= key_part->length;
1409
/* Allocate bitmaps */
1411
bitmap_size= share->column_bitmap_size;
1412
if (!(bitmaps= (unsigned char*) alloc_root(&outparam->mem_root, bitmap_size*3)))
1414
outparam->def_read_set.init((my_bitmap_map*) bitmaps, share->fields);
1415
outparam->def_write_set.init((my_bitmap_map*) (bitmaps+bitmap_size), share->fields);
1416
outparam->tmp_set.init((my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields);
1417
outparam->default_column_bitmaps();
1419
/* The table struct is now initialized; Open the table */
1421
if (db_stat && open_mode != OTM_ALTER)
1424
if ((ha_err= (outparam->file->
1425
ha_open(outparam, share->normalized_path.str,
1426
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
1427
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
1428
(db_stat & HA_WAIT_IF_LOCKED) ? HA_OPEN_WAIT_IF_LOCKED :
1429
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
1430
HA_OPEN_ABORT_IF_LOCKED :
1431
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
1433
/* Set a flag if the table is crashed and it can be auto. repaired */
1434
share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
1435
outparam->file->auto_repair() &&
1436
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
1440
case HA_ERR_NO_SUCH_TABLE:
1442
The table did not exists in storage engine, use same error message
1443
as if the .frm file didn't exist
1450
Too many files opened, use same error message as if the .frm
1457
outparam->file->print_error(ha_err, MYF(0));
1458
error_reported= true;
1459
if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
1467
#if defined(HAVE_purify)
1468
memset(bitmaps, 0, bitmap_size*3);
1471
session->status_var.opened_tables++;
1476
if (!error_reported && !(prgflag & DONT_GIVE_ERROR))
1477
share->open_table_error(error, my_errno, 0);
1478
delete outparam->file;
1479
outparam->file= 0; // For easier error checking
1480
outparam->db_stat= 0;
1481
free_root(&outparam->mem_root, MYF(0)); // Safe to call on zeroed root
1482
free((char*) outparam->alias);
1487
Free information allocated by openfrm
1491
table Table object to free
1492
free_share Is 1 if we also want to free table_share
1495
int Table::closefrm(bool free_share)
83
error= cursor->close();
1500
error= file->close();
1501
free((char*) alias);
87
1505
for (Field **ptr=field ; *ptr ; ptr++)
94
cursor= 0; /* For easier errorchecking */
1510
file= 0; /* For easier errorchecking */
1513
if (s->tmp_table == NO_TMP_TABLE)
1514
TableShare::release(s);
1516
s->free_table_share();
1518
free_root(&mem_root, MYF(0));
106
mem_root.free_root(MYF(0));
110
void Table::resetTable(Session *session,
112
uint32_t db_stat_arg)
125
db_stat= db_stat_arg;
128
record[0]= (unsigned char *) NULL;
129
record[1]= (unsigned char *) NULL;
131
insert_values.clear();
133
next_number_field= NULL;
134
found_next_number_field= NULL;
135
timestamp_field= NULL;
137
pos_in_table_list= NULL;
147
derived_select_number= 0;
148
current_lock= F_UNLCK;
162
open_placeholder= false;
163
locked_by_name= false;
166
auto_increment_field_not_null= false;
167
alias_name_used= false;
170
quick_condition_rows= 0;
172
timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
177
covering_keys.reset();
182
keys_in_use_for_query.reset();
183
keys_in_use_for_group_by.reset();
184
keys_in_use_for_order_by.reset();
186
memset(quick_rows, 0, sizeof(ha_rows) * MAX_KEY);
187
memset(const_key_parts, 0, sizeof(ha_rows) * MAX_KEY);
189
memset(quick_key_parts, 0, sizeof(unsigned int) * MAX_KEY);
190
memset(quick_n_ranges, 0, sizeof(unsigned int) * MAX_KEY);
192
memory::init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
197
1524
/* Deallocate temporary blob storage */
1398
2923
session->mem_root= mem_root_save;
2924
table->free_tmp_table(session);
1404
2928
/****************************************************************************/
1406
void Table::column_bitmaps_set(boost::dynamic_bitset<>& read_set_arg,
1407
boost::dynamic_bitset<>& write_set_arg)
1409
read_set= &read_set_arg;
1410
write_set= &write_set_arg;
1414
const boost::dynamic_bitset<> Table::use_all_columns(boost::dynamic_bitset<>& in_map)
1416
const boost::dynamic_bitset<> old= in_map;
1417
in_map= getShare()->all_set;
2931
Create a reduced Table object with properly set up Field list from a
2932
list of field definitions.
2934
The created table doesn't have a table handler associated with
2935
it, has no keys, no group/distinct, no copy_funcs array.
2936
The sole purpose of this Table object is to use the power of Field
2937
class to read/write data to/from table->record[0]. Then one can store
2938
the record in any container (RB tree, hash, etc).
2939
The table is created in Session mem_root, so are the table's fields.
2940
Consequently, if you don't BLOB fields, you don't need to free it.
2942
@param session connection handle
2943
@param field_list list of column definitions
2946
0 if out of memory, Table object in case of success
2949
Table *create_virtual_tmp_table(Session *session, List<CreateField> &field_list)
2951
uint32_t field_count= field_list.elements;
2952
uint32_t blob_count= 0;
2954
CreateField *cdef; /* column definition */
2955
uint32_t record_length= 0;
2956
uint32_t null_count= 0; /* number of columns which may be null */
2957
uint32_t null_pack_length; /* NULL representation array length */
2958
uint32_t *blob_field;
2959
unsigned char *bitmaps;
2963
if (!multi_alloc_root(session->mem_root,
2964
&table, sizeof(*table),
2965
&share, sizeof(*share),
2966
&field, (field_count + 1) * sizeof(Field*),
2967
&blob_field, (field_count+1) *sizeof(uint32_t),
2968
&bitmaps, bitmap_buffer_size(field_count)*2,
2972
memset(table, 0, sizeof(*table));
2973
memset(share, 0, sizeof(*share));
2974
table->field= field;
2976
share->blob_field= blob_field;
2977
share->fields= field_count;
2978
share->blob_ptr_size= portable_sizeof_char_ptr;
2979
table->setup_tmp_table_column_bitmaps(bitmaps);
2981
/* Create all fields and calculate the total length of record */
2982
List_iterator_fast<CreateField> it(field_list);
2983
while ((cdef= it++))
2985
*field= make_field(share, NULL, 0, cdef->length,
2986
(unsigned char*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
2987
f_maybe_null(cdef->pack_flag) ? 1 : 0,
2988
cdef->pack_flag, cdef->sql_type, cdef->charset,
2990
cdef->interval, cdef->field_name);
2993
(*field)->init(table);
2994
record_length+= (*field)->pack_length();
2995
if (! ((*field)->flags & NOT_NULL_FLAG))
2998
if ((*field)->flags & BLOB_FLAG)
2999
share->blob_field[blob_count++]= (uint32_t) (field - table->field);
3003
*field= NULL; /* mark the end of the list */
3004
share->blob_field[blob_count]= 0; /* mark the end of the list */
3005
share->blob_fields= blob_count;
3007
null_pack_length= (null_count + 7)/8;
3008
share->reclength= record_length + null_pack_length;
3009
share->rec_buff_length= ALIGN_SIZE(share->reclength + 1);
3010
table->record[0]= (unsigned char*) session->alloc(share->rec_buff_length);
3011
if (!table->record[0])
3014
if (null_pack_length)
3016
table->null_flags= (unsigned char*) table->record[0];
3017
share->null_fields= null_count;
3018
share->null_bytes= null_pack_length;
3021
table->in_use= session; /* field->reset() may access table->in_use */
3023
/* Set up field pointers */
3024
unsigned char *null_pos= table->record[0];
3025
unsigned char *field_pos= null_pos + share->null_bytes;
3026
uint32_t null_bit= 1;
3028
for (field= table->field; *field; ++field)
3030
Field *cur_field= *field;
3031
if ((cur_field->flags & NOT_NULL_FLAG))
3032
cur_field->move_field(field_pos);
3035
cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
3037
if (null_bit == (1 << 8))
3045
field_pos+= cur_field->pack_length();
3050
for (field= table->field; *field; ++field)
3051
delete *field; /* just invokes field destructor */
3055
bool Table::open_tmp_table()
3058
if ((error=file->ha_open(this, s->table_name.str,O_RDWR,
3059
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
3061
file->print_error(error,MYF(0));
3065
(void) file->extra(HA_EXTRA_QUICK); /* Faster */
3071
Create MyISAM temporary table
3074
create_myisam_tmp_table()
3075
keyinfo Description of the index (there is always one index)
3076
start_recinfo MyISAM's column descriptions
3077
recinfo INOUT End of MyISAM's column descriptions
3081
Create a MyISAM temporary table according to passed description. The is
3082
assumed to have one unique index or constraint.
3084
The passed array or MI_COLUMNDEF structures must have this form:
3086
1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
3087
when there are many nullable columns)
3089
3. One free MI_COLUMNDEF element (*recinfo points here)
3091
This function may use the free element to create hash column for unique
3099
bool Table::create_myisam_tmp_table(KEY *keyinfo,
3100
MI_COLUMNDEF *start_recinfo,
3101
MI_COLUMNDEF **recinfo,
3106
MI_UNIQUEDEF uniquedef;
3107
TableShare *share= s;
3110
{ // Get keys for ni_create
3111
bool using_unique_constraint= 0;
3112
HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&this->mem_root,
3113
sizeof(*seg) * keyinfo->key_parts);
3117
memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
3118
if (keyinfo->key_length >= file->max_key_length() ||
3119
keyinfo->key_parts > file->max_key_parts() ||
3122
/* Can't create a key; Make a unique constraint instead of a key */
3125
using_unique_constraint=1;
3126
memset(&uniquedef, 0, sizeof(uniquedef));
3127
uniquedef.keysegs=keyinfo->key_parts;
3129
uniquedef.null_are_equal=1;
3131
/* Create extra column for hash value */
3132
memset(*recinfo, 0, sizeof(**recinfo));
3133
(*recinfo)->type= FIELD_CHECK;
3134
(*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
3136
share->reclength+=MI_UNIQUE_HASH_LENGTH;
3140
/* Create an unique key */
3141
memset(&keydef, 0, sizeof(keydef));
3142
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
3143
keydef.keysegs= keyinfo->key_parts;
3146
for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
3148
Field *key_field=keyinfo->key_part[i].field;
3150
seg->language= key_field->charset()->number;
3151
seg->length= keyinfo->key_part[i].length;
3152
seg->start= keyinfo->key_part[i].offset;
3153
if (key_field->flags & BLOB_FLAG)
3156
((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
3157
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
3158
seg->bit_start= (uint8_t)(key_field->pack_length()
3159
- share->blob_ptr_size);
3160
seg->flag= HA_BLOB_PART;
3161
seg->length= 0; // Whole blob in unique constraint
3165
seg->type= keyinfo->key_part[i].type;
3167
if (!(key_field->flags & NOT_NULL_FLAG))
3169
seg->null_bit= key_field->null_bit;
3170
seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) record[0]);
3172
We are using a GROUP BY on something that contains NULL
3173
In this case we have to tell MyISAM that two NULL should
3174
on INSERT be regarded at the same value
3176
if (!using_unique_constraint)
3177
keydef.flag|= HA_NULL_ARE_EQUAL;
3181
MI_CREATE_INFO create_info;
3182
memset(&create_info, 0, sizeof(create_info));
3184
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
3186
create_info.data_file_length= ~(uint64_t) 0;
3188
if ((error=mi_create(share->table_name.str, share->keys, &keydef,
3189
(uint32_t) (*recinfo-start_recinfo),
3191
share->uniques, &uniquedef,
3193
HA_CREATE_TMP_TABLE)))
3195
file->print_error(error,MYF(0));
3199
status_var_increment(in_use->status_var.created_tmp_disk_tables);
3200
share->db_record_offset= 1;
3207
void Table::free_tmp_table(Session *session)
3209
MEM_ROOT own_root= mem_root;
3210
const char *save_proc_info;
3212
save_proc_info=session->get_proc_info();
3213
session->set_proc_info("removing tmp table");
3215
// Release latches since this can take a long time
3216
ha_release_temporary_latches(session);
3221
file->ha_drop_table(s->table_name.str);
3223
s->db_type()->deleteTable(session, s->table_name.str);
3228
for (Field **ptr= field ; *ptr ; ptr++)
3232
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
3233
session->set_proc_info(save_proc_info);
3237
If a HEAP table gets full, create a MyISAM table and copy all rows
3241
bool create_myisam_from_heap(Session *session, Table *table,
3242
MI_COLUMNDEF *start_recinfo,
3243
MI_COLUMNDEF **recinfo,
3244
int error, bool ignore_last_dupp_key_error)
3248
const char *save_proc_info;
3251
if (table->s->db_type() != heap_engine ||
3252
error != HA_ERR_RECORD_FILE_FULL)
3254
table->file->print_error(error,MYF(0));
3258
// Release latches since this can take a long time
3259
ha_release_temporary_latches(session);
3263
new_table.s= &share;
3264
new_table.s->storage_engine= myisam_engine;
3265
if (!(new_table.file= get_new_handler(&share, &new_table.mem_root,
3266
new_table.s->db_type())))
3267
return true; // End of memory
3269
save_proc_info=session->get_proc_info();
3270
session->set_proc_info("converting HEAP to MyISAM");
3272
if (new_table.create_myisam_tmp_table(table->key_info, start_recinfo,
3273
recinfo, session->lex->select_lex.options |
3276
if (new_table.open_tmp_table())
3278
if (table->file->indexes_are_disabled())
3279
new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
3280
table->file->ha_index_or_rnd_end();
3281
table->file->ha_rnd_init(1);
3284
new_table.file->extra(HA_EXTRA_NO_ROWS);
3285
new_table.no_rows=1;
3288
/* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
3289
new_table.file->extra(HA_EXTRA_WRITE_CACHE);
3292
copy all old rows from heap table to MyISAM table
3293
This is the only code that uses record[1] to read/write but this
3294
is safe as this is a temporary MyISAM table without timestamp/autoincrement.
3296
while (!table->file->rnd_next(new_table.record[1]))
3298
write_err= new_table.file->ha_write_row(new_table.record[1]);
3302
/* copy row that filled HEAP table */
3303
if ((write_err=new_table.file->ha_write_row(table->record[0])))
3305
if (new_table.file->is_fatal_error(write_err, HA_CHECK_DUP) ||
3306
!ignore_last_dupp_key_error)
3310
/* remove heap table and change to use myisam table */
3311
(void) table->file->ha_rnd_end();
3312
(void) table->file->close(); // This deletes the table !
3315
new_table.s= table->s; // Keep old share
3319
table->file->change_table_ptr(table, table->s);
3320
table->use_all_columns();
3323
const char *new_proc_info=
3324
(!strcmp(save_proc_info,"Copying to tmp table") ?
3325
"Copying to tmp table on disk" : save_proc_info);
3326
session->set_proc_info(new_proc_info);
3331
table->file->print_error(write_err, MYF(0));
3332
(void) table->file->ha_rnd_end();
3333
(void) new_table.file->close();
3335
new_table.s->db_type()->deleteTable(session, new_table.s->table_name.str);
3337
delete new_table.file;
3338
session->set_proc_info(save_proc_info);
3339
table->mem_root= new_table.mem_root;
3343
my_bitmap_map *Table::use_all_columns(MyBitmap *bitmap)
3345
my_bitmap_map *old= bitmap->getBitmap();
3346
bitmap->setBitmap(s->all_set.getBitmap());
1421
void Table::restore_column_map(const boost::dynamic_bitset<>& old)
3350
void Table::restore_column_map(my_bitmap_map *old)
1423
for (boost::dynamic_bitset<>::size_type i= 0; i < old.size(); i++)
3352
read_set->setBitmap(old);
1436
3355
uint32_t Table::find_shortest_key(const key_map *usable_keys)