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"
49
#include "drizzled/plugin/storage_engine.h"
51
36
#include <drizzled/item/string.h>
52
37
#include <drizzled/item/int.h>
53
38
#include <drizzled/item/decimal.h>
54
39
#include <drizzled/item/float.h>
55
40
#include <drizzled/item/null.h>
56
#include <drizzled/temporal.h>
58
#include <drizzled/refresh_version.h>
60
#include "drizzled/table/singular.h"
62
#include "drizzled/table_proto.h"
42
#include <drizzled/table_proto.h>
64
49
using namespace std;
69
extern plugin::StorageEngine *heap_engine;
70
extern plugin::StorageEngine *myisam_engine;
72
/* Functions defined in this cursor */
51
/* Functions defined in this file */
53
void open_table_error(TableShare *share, int error, int db_errno,
54
myf errortype, int errarg);
74
56
/*************************************************************************/
76
// @note this should all be the destructor
77
int Table::delete_table(bool free_share)
58
/* Get column name from column hash */
60
static unsigned char *get_field_name(Field **buff, size_t *length, bool)
62
*length= (uint32_t) strlen((*buff)->field_name);
63
return (unsigned char*) (*buff)->field_name;
68
Returns pointer to '.frm' extension of the file name.
75
Checks file name part starting with the rightmost '.' character,
76
and returns it if it is equal to '.dfe'.
79
It is a good idea to get rid of this function modifying the code
80
to garantee that the functions presently calling fn_rext() always
81
get arguments in the same format: either with '.frm' or without '.frm'.
84
Pointer to the '.frm' extension. If there is no extension,
85
or extension is not '.frm', pointer at the end of file name.
88
char *fn_rext(char *name)
90
char *res= strrchr(name, '.');
91
if (res && !strcmp(res, ".dfe"))
93
return name + strlen(name);
96
static TABLE_CATEGORY get_table_category(const LEX_STRING *db)
100
if ((db->length == INFORMATION_SCHEMA_NAME.length()) &&
101
(my_strcasecmp(system_charset_info,
102
INFORMATION_SCHEMA_NAME.c_str(),
105
return TABLE_CATEGORY_INFORMATION;
108
return TABLE_CATEGORY_USER;
113
Allocate a setup TableShare structure
117
TableList Take database and table name from there
118
key Table cache key (db \0 table_name \0...)
119
key_length Length of key
122
0 Error (out of memory)
126
TableShare *alloc_table_share(TableList *table_list, char *key,
131
char *key_buff, *path_buff;
132
char path[FN_REFLEN];
133
uint32_t path_length;
135
path_length= build_table_filename(path, sizeof(path) - 1,
137
table_list->table_name, false);
138
init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
139
if (multi_alloc_root(&mem_root,
140
&share, sizeof(*share),
141
&key_buff, key_length,
142
&path_buff, path_length + 1,
145
memset(share, 0, sizeof(*share));
147
share->set_table_cache_key(key_buff, key, key_length);
149
share->path.str= path_buff;
150
share->path.length= path_length;
151
strcpy(share->path.str, path);
152
share->normalized_path.str= share->path.str;
153
share->normalized_path.length= path_length;
155
share->version= refresh_version;
157
memcpy(&share->mem_root, &mem_root, sizeof(mem_root));
158
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
159
pthread_cond_init(&share->cond, NULL);
165
static enum_field_types proto_field_type_to_drizzle_type(uint32_t proto_field_type)
167
enum_field_types field_type;
169
switch(proto_field_type)
171
case drizzled::message::Table::Field::TINYINT:
172
field_type= DRIZZLE_TYPE_TINY;
174
case drizzled::message::Table::Field::INTEGER:
175
field_type= DRIZZLE_TYPE_LONG;
177
case drizzled::message::Table::Field::DOUBLE:
178
field_type= DRIZZLE_TYPE_DOUBLE;
180
case drizzled::message::Table::Field::TIMESTAMP:
181
field_type= DRIZZLE_TYPE_TIMESTAMP;
183
case drizzled::message::Table::Field::BIGINT:
184
field_type= DRIZZLE_TYPE_LONGLONG;
186
case drizzled::message::Table::Field::DATETIME:
187
field_type= DRIZZLE_TYPE_DATETIME;
189
case drizzled::message::Table::Field::DATE:
190
field_type= DRIZZLE_TYPE_DATE;
192
case drizzled::message::Table::Field::VARCHAR:
193
field_type= DRIZZLE_TYPE_VARCHAR;
195
case drizzled::message::Table::Field::DECIMAL:
196
field_type= DRIZZLE_TYPE_NEWDECIMAL;
198
case drizzled::message::Table::Field::ENUM:
199
field_type= DRIZZLE_TYPE_ENUM;
201
case drizzled::message::Table::Field::BLOB:
202
field_type= DRIZZLE_TYPE_BLOB;
205
field_type= DRIZZLE_TYPE_TINY; /* Set value to kill GCC warning */
212
static Item *default_value_item(enum_field_types field_type,
213
const CHARSET_INFO *charset,
214
bool default_null, const string *default_value,
215
const string *default_bin_value)
217
Item *default_item= NULL;
222
return new Item_null();
227
case DRIZZLE_TYPE_TINY:
228
case DRIZZLE_TYPE_LONG:
229
case DRIZZLE_TYPE_LONGLONG:
230
default_item= new Item_int(default_value->c_str(),
231
(int64_t) my_strtoll10(default_value->c_str(),
234
default_value->length());
236
case DRIZZLE_TYPE_DOUBLE:
237
default_item= new Item_float(default_value->c_str(),
238
default_value->length());
240
case DRIZZLE_TYPE_NULL:
242
case DRIZZLE_TYPE_TIMESTAMP:
243
case DRIZZLE_TYPE_DATETIME:
244
case DRIZZLE_TYPE_DATE:
245
if (default_value->compare("NOW()") == 0)
247
case DRIZZLE_TYPE_ENUM:
248
default_item= new Item_string(default_value->c_str(),
249
default_value->length(),
250
system_charset_info);
252
case DRIZZLE_TYPE_VARCHAR:
253
case DRIZZLE_TYPE_BLOB: /* Blob is here due to TINYTEXT. Feel the hate. */
254
if (charset==&my_charset_bin)
256
default_item= new Item_string(default_bin_value->c_str(),
257
default_bin_value->length(),
262
default_item= new Item_string(default_value->c_str(),
263
default_value->length(),
264
system_charset_info);
267
case DRIZZLE_TYPE_NEWDECIMAL:
268
default_item= new Item_decimal(default_value->c_str(),
269
default_value->length(),
270
system_charset_info);
277
int parse_table_proto(Session *session,
278
drizzled::message::Table &table,
282
handler *handler_file= NULL;
285
share->storage_engine= ha_resolve_by_name(session, table.engine().name());
288
drizzled::message::Table::TableOptions table_options;
290
if (table.has_options())
291
table_options= table.options();
293
uint32_t db_create_options= HA_OPTION_LONG_BLOB_PTR;
295
if (table_options.has_pack_keys())
297
if (table_options.pack_keys())
298
db_create_options|= HA_OPTION_PACK_KEYS;
300
db_create_options|= HA_OPTION_NO_PACK_KEYS;
303
if (table_options.pack_record())
304
db_create_options|= HA_OPTION_PACK_RECORD;
306
if (table_options.has_checksum())
308
if (table_options.checksum())
309
db_create_options|= HA_OPTION_CHECKSUM;
311
db_create_options|= HA_OPTION_NO_CHECKSUM;
314
/* db_create_options was stored as 2 bytes in FRM
315
Any HA_OPTION_ that doesn't fit into 2 bytes was silently truncated away.
317
share->db_create_options= (db_create_options & 0x0000FFFF);
318
share->db_options_in_use= share->db_create_options;
321
share->avg_row_length= table_options.has_avg_row_length() ?
322
table_options.avg_row_length() : 0;
324
share->page_checksum= table_options.has_page_checksum() ?
325
(table_options.page_checksum()?HA_CHOICE_YES:HA_CHOICE_NO)
328
share->row_type= table_options.has_row_type() ?
329
(enum row_type) table_options.row_type() : ROW_TYPE_DEFAULT;
331
share->block_size= table_options.has_block_size() ?
332
table_options.block_size() : 0;
334
share->table_charset= get_charset(table_options.has_collation_id()?
335
table_options.collation_id() : 0);
337
if (!share->table_charset)
339
/* unknown charset in head[38] or pre-3.23 frm */
340
if (use_mb(default_charset_info))
342
/* Warn that we may be changing the size of character columns */
343
errmsg_printf(ERRMSG_LVL_WARN,
344
_("'%s' had no or invalid character set, "
345
"and default character set is multi-byte, "
346
"so character column sizes may have changed"),
349
share->table_charset= default_charset_info;
352
share->db_record_offset= 1;
354
share->blob_ptr_size= portable_sizeof_char_ptr; // more bonghits.
356
share->db_low_byte_first= true;
358
share->max_rows= table_options.has_max_rows() ?
359
table_options.max_rows() : 0;
361
share->min_rows= table_options.has_min_rows() ?
362
table_options.min_rows() : 0;
364
share->keys= table.indexes_size();
367
for (int indx= 0; indx < table.indexes_size(); indx++)
368
share->key_parts+= table.indexes(indx).index_part_size();
370
share->key_info= (KEY*) alloc_root(&share->mem_root,
371
table.indexes_size() * sizeof(KEY)
372
+share->key_parts*sizeof(KEY_PART_INFO));
374
KEY_PART_INFO *key_part;
376
key_part= reinterpret_cast<KEY_PART_INFO*>
377
(share->key_info+table.indexes_size());
380
ulong *rec_per_key= (ulong*) alloc_root(&share->mem_root,
381
sizeof(ulong*)*share->key_parts);
383
share->keynames.count= table.indexes_size();
384
share->keynames.name= NULL;
385
share->keynames.type_names= (const char**)
386
alloc_root(&share->mem_root, sizeof(char*) * (table.indexes_size()+1));
388
share->keynames.type_lengths= (unsigned int*)
389
alloc_root(&share->mem_root,
390
sizeof(unsigned int) * (table.indexes_size()+1));
392
share->keynames.type_names[share->keynames.count]= NULL;
393
share->keynames.type_lengths[share->keynames.count]= 0;
395
KEY* keyinfo= share->key_info;
396
for (int keynr= 0; keynr < table.indexes_size(); keynr++, keyinfo++)
398
drizzled::message::Table::Index indx= table.indexes(keynr);
403
if (indx.is_unique())
404
keyinfo->flags|= HA_NOSAME;
406
if (indx.has_options())
408
drizzled::message::Table::Index::IndexOptions indx_options= indx.options();
409
if (indx_options.pack_key())
410
keyinfo->flags|= HA_PACK_KEY;
412
if (indx_options.var_length_key())
413
keyinfo->flags|= HA_VAR_LENGTH_PART;
415
if (indx_options.null_part_key())
416
keyinfo->flags|= HA_NULL_PART_KEY;
418
if (indx_options.binary_pack_key())
419
keyinfo->flags|= HA_BINARY_PACK_KEY;
421
if (indx_options.has_partial_segments())
422
keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
424
if (indx_options.auto_generated_key())
425
keyinfo->flags|= HA_GENERATED_KEY;
427
if (indx_options.has_key_block_size())
429
keyinfo->flags|= HA_USES_BLOCK_SIZE;
430
keyinfo->block_size= indx_options.key_block_size();
434
keyinfo->block_size= 0;
441
case drizzled::message::Table::Index::UNKNOWN_INDEX:
442
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
444
case drizzled::message::Table::Index::BTREE:
445
keyinfo->algorithm= HA_KEY_ALG_BTREE;
447
case drizzled::message::Table::Index::RTREE:
448
keyinfo->algorithm= HA_KEY_ALG_RTREE;
450
case drizzled::message::Table::Index::HASH:
451
keyinfo->algorithm= HA_KEY_ALG_HASH;
453
case drizzled::message::Table::Index::FULLTEXT:
454
keyinfo->algorithm= HA_KEY_ALG_FULLTEXT;
457
/* TODO: suitable warning ? */
458
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
462
keyinfo->key_length= indx.key_length();
464
keyinfo->key_parts= indx.index_part_size();
466
keyinfo->key_part= key_part;
467
keyinfo->rec_per_key= rec_per_key;
469
for (unsigned int partnr= 0;
470
partnr < keyinfo->key_parts;
471
partnr++, key_part++)
473
drizzled::message::Table::Index::IndexPart part;
474
part= indx.index_part(partnr);
478
key_part->field= NULL;
479
key_part->fieldnr= part.fieldnr() + 1; // start from 1.
480
key_part->null_bit= 0;
481
/* key_part->null_offset is only set if null_bit (see later) */
482
/* key_part->key_type= */ /* I *THINK* this may be okay.... */
483
/* key_part->type ???? */
484
key_part->key_part_flag= 0;
485
if (part.has_in_reverse_order())
486
key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
488
key_part->length= part.compare_length();
490
key_part->store_length= key_part->length;
492
/* key_part->offset is set later */
493
key_part->key_type= part.key_type();
497
if (!indx.has_comment())
499
keyinfo->comment.length= 0;
500
keyinfo->comment.str= NULL;
504
keyinfo->flags|= HA_USES_COMMENT;
505
keyinfo->comment.length= indx.comment().length();
506
keyinfo->comment.str= strmake_root(&share->mem_root,
507
indx.comment().c_str(),
508
keyinfo->comment.length);
511
keyinfo->name= strmake_root(&share->mem_root,
513
indx.name().length());
515
share->keynames.type_names[keynr]= keyinfo->name;
516
share->keynames.type_lengths[keynr]= indx.name().length();
519
share->keys_for_keyread.reset();
520
set_prefix(share->keys_in_use, share->keys);
522
if (table_options.has_connect_string())
524
size_t len= table_options.connect_string().length();
525
const char* str= table_options.connect_string().c_str();
527
share->connect_string.length= len;
528
share->connect_string.str= strmake_root(&share->mem_root, str, len);
531
if (table_options.has_comment())
533
size_t len= table_options.comment().length();
534
const char* str= table_options.comment().c_str();
536
share->comment.length= len;
537
share->comment.str= strmake_root(&share->mem_root, str, len);
540
share->key_block_size= table_options.has_key_block_size() ?
541
table_options.key_block_size() : 0;
543
share->fields= table.field_size();
545
share->field= (Field**) alloc_root(&share->mem_root,
546
((share->fields+1) * sizeof(Field*)));
547
share->field[share->fields]= NULL;
549
uint32_t null_fields= 0;
552
uint32_t *field_offsets= (uint32_t*)malloc(share->fields * sizeof(uint32_t));
553
uint32_t *field_pack_length=(uint32_t*)malloc(share->fields*sizeof(uint32_t));
555
assert(field_offsets && field_pack_length); // TODO: fixme
557
uint32_t interval_count= 0;
558
uint32_t interval_parts= 0;
560
uint32_t stored_columns_reclength= 0;
562
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
564
drizzled::message::Table::Field pfield= table.field(fieldnr);
565
if (pfield.has_constraints() && pfield.constraints().is_nullable())
568
enum_field_types drizzle_field_type=
569
proto_field_type_to_drizzle_type(pfield.type());
571
field_offsets[fieldnr]= stored_columns_reclength;
573
/* the below switch is very similar to
574
CreateField::create_length_to_internal_length in field.cc
575
(which should one day be replace by just this code)
577
switch(drizzle_field_type)
579
case DRIZZLE_TYPE_BLOB:
580
case DRIZZLE_TYPE_VARCHAR:
582
drizzled::message::Table::Field::StringFieldOptions field_options=
583
pfield.string_options();
585
const CHARSET_INFO *cs= get_charset(field_options.has_collation_id()?
586
field_options.collation_id() : 0);
589
cs= default_charset_info;
591
field_pack_length[fieldnr]=
592
calc_pack_length(drizzle_field_type,
593
field_options.length() * cs->mbmaxlen);
597
case DRIZZLE_TYPE_ENUM:
599
drizzled::message::Table::Field::SetFieldOptions field_options=
600
pfield.set_options();
602
field_pack_length[fieldnr]=
603
get_enum_pack_length(field_options.field_value_size());
606
interval_parts+= field_options.field_value_size();
609
case DRIZZLE_TYPE_NEWDECIMAL:
611
drizzled::message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
613
field_pack_length[fieldnr]=
614
my_decimal_get_binary_size(fo.precision(), fo.scale());
618
/* Zero is okay here as length is fixed for other types. */
619
field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
622
share->reclength+= field_pack_length[fieldnr];
623
stored_columns_reclength+= field_pack_length[fieldnr];
627
/* data_offset added to stored_rec_length later */
628
share->stored_rec_length= stored_columns_reclength;
630
share->null_fields= null_fields;
632
ulong null_bits= null_fields;
633
if (!table_options.pack_record())
635
ulong data_offset= (null_bits + 7)/8;
638
share->reclength+= data_offset;
639
share->stored_rec_length+= data_offset;
641
ulong rec_buff_length;
643
rec_buff_length= ALIGN_SIZE(share->reclength + 1);
644
share->rec_buff_length= rec_buff_length;
646
unsigned char* record= NULL;
648
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
652
memset(record, 0, rec_buff_length);
656
if (!table_options.pack_record())
658
null_count++; // one bit for delete mark.
662
share->default_values= record;
666
share->intervals= (TYPELIB*)alloc_root(&share->mem_root,
667
interval_count*sizeof(TYPELIB));
670
share->intervals= NULL;
672
share->fieldnames.type_names= (const char**)alloc_root(&share->mem_root,
673
(share->fields+1)*sizeof(char*));
675
share->fieldnames.type_lengths= (unsigned int*) alloc_root(&share->mem_root,
676
(share->fields+1)*sizeof(unsigned int));
678
share->fieldnames.type_names[share->fields]= NULL;
679
share->fieldnames.type_lengths[share->fields]= 0;
680
share->fieldnames.count= share->fields;
683
/* Now fix the TYPELIBs for the intervals (enum values)
687
uint32_t interval_nr= 0;
689
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
691
drizzled::message::Table::Field pfield= table.field(fieldnr);
694
share->fieldnames.type_names[fieldnr]= strmake_root(&share->mem_root,
695
pfield.name().c_str(),
696
pfield.name().length());
698
share->fieldnames.type_lengths[fieldnr]= pfield.name().length();
701
if (pfield.type() != drizzled::message::Table::Field::ENUM)
704
drizzled::message::Table::Field::SetFieldOptions field_options=
705
pfield.set_options();
707
const CHARSET_INFO *charset= get_charset(field_options.has_collation_id()?
708
field_options.collation_id() : 0);
711
charset= default_charset_info;
713
TYPELIB *t= &(share->intervals[interval_nr]);
715
t->type_names= (const char**)alloc_root(&share->mem_root,
716
(field_options.field_value_size()+1)*sizeof(char*));
718
t->type_lengths= (unsigned int*) alloc_root(&share->mem_root,
719
(field_options.field_value_size()+1)*sizeof(unsigned int));
721
t->type_names[field_options.field_value_size()]= NULL;
722
t->type_lengths[field_options.field_value_size()]= 0;
724
t->count= field_options.field_value_size();
727
for (int n= 0; n < field_options.field_value_size(); n++)
729
t->type_names[n]= strmake_root(&share->mem_root,
730
field_options.field_value(n).c_str(),
731
field_options.field_value(n).length());
733
/* Go ask the charset what the length is as for "" length=1
734
and there's stripping spaces or some other crack going on.
737
lengthsp= charset->cset->lengthsp(charset, t->type_names[n],
738
field_options.field_value(n).length());
739
t->type_lengths[n]= lengthsp;
745
/* and read the fields */
748
bool use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
751
use_hash= !hash_init(&share->name_hash,
754
(hash_get_key) get_field_name, 0, 0);
756
unsigned char* null_pos= record;;
757
int null_bit_pos= (table_options.pack_record()) ? 0 : 1;
759
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
761
drizzled::message::Table::Field pfield= table.field(fieldnr);
763
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
765
switch(pfield.format())
767
case drizzled::message::Table::Field::DefaultFormat:
768
column_format= COLUMN_FORMAT_TYPE_DEFAULT;
770
case drizzled::message::Table::Field::FixedFormat:
771
column_format= COLUMN_FORMAT_TYPE_FIXED;
773
case drizzled::message::Table::Field::DynamicFormat:
774
column_format= COLUMN_FORMAT_TYPE_DYNAMIC;
780
Field::utype unireg_type= Field::NONE;
782
if (pfield.has_numeric_options()
783
&& pfield.numeric_options().is_autoincrement())
785
unireg_type= Field::NEXT_NUMBER;
788
if (pfield.has_options()
789
&& pfield.options().has_default_value()
790
&& pfield.options().default_value().compare("NOW()") == 0)
792
if (pfield.options().has_update_value()
793
&& pfield.options().update_value().compare("NOW()") == 0)
795
unireg_type= Field::TIMESTAMP_DNUN_FIELD;
797
else if (!pfield.options().has_update_value())
799
unireg_type= Field::TIMESTAMP_DN_FIELD;
802
assert(1); // Invalid update value.
804
else if (pfield.has_options()
805
&& pfield.options().has_update_value()
806
&& pfield.options().update_value().compare("NOW()") == 0)
808
unireg_type= Field::TIMESTAMP_UN_FIELD;
812
if (!pfield.has_comment())
814
comment.str= (char*)"";
819
size_t len= pfield.comment().length();
820
const char* str= pfield.comment().c_str();
822
comment.str= strmake_root(&share->mem_root, str, len);
826
enum_field_types field_type;
828
field_type= proto_field_type_to_drizzle_type(pfield.type());
830
const CHARSET_INFO *charset= &my_charset_bin;
832
if (field_type==DRIZZLE_TYPE_BLOB
833
|| field_type==DRIZZLE_TYPE_VARCHAR)
835
drizzled::message::Table::Field::StringFieldOptions field_options=
836
pfield.string_options();
838
charset= get_charset(field_options.has_collation_id()?
839
field_options.collation_id() : 0);
842
charset= default_charset_info;
846
if (field_type==DRIZZLE_TYPE_ENUM)
848
drizzled::message::Table::Field::SetFieldOptions field_options=
849
pfield.set_options();
851
charset= get_charset(field_options.has_collation_id()?
852
field_options.collation_id() : 0);
855
charset= default_charset_info;
859
Item *default_value= NULL;
861
if (pfield.options().has_default_value()
862
|| pfield.options().has_default_null()
863
|| pfield.options().has_default_bin_value())
865
default_value= default_value_item(field_type,
867
pfield.options().default_null(),
868
&pfield.options().default_value(),
869
&pfield.options().default_bin_value());
872
uint32_t pack_flag= pfield.pack_flag(); /* TODO: MUST DIE */
874
Table temp_table; /* Use this so that BLOB DEFAULT '' works */
875
memset(&temp_table, 0, sizeof(temp_table));
877
temp_table.in_use= session;
878
temp_table.s->db_low_byte_first= 1; //handler->low_byte_first();
879
temp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
881
Field* f= make_field(share, &share->mem_root,
882
record+field_offsets[fieldnr]+data_offset,
883
pfield.options().length(),
889
(Field::utype) MTYP_TYPENR(unireg_type),
890
((field_type==DRIZZLE_TYPE_ENUM)?
891
share->intervals+(interval_nr++)
893
share->fieldnames.type_names[fieldnr]);
895
share->field[fieldnr]= f;
897
f->init(&temp_table); /* blob default values need table obj */
899
if (!(f->flags & NOT_NULL_FLAG))
901
*f->null_ptr|= f->null_bit;
902
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
909
enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
910
session->count_cuted_fields= CHECK_FIELD_WARN;
911
int res= default_value->save_in_field(f, 1);
912
session->count_cuted_fields= old_count_cuted_fields;
913
if (res != 0 && res != 3)
915
my_error(ER_INVALID_DEFAULT, MYF(0), f->field_name);
920
else if (f->real_type() == DRIZZLE_TYPE_ENUM &&
921
(f->flags & NOT_NULL_FLAG))
924
f->store((int64_t) 1, true);
929
/* hack to undo f->init() */
933
f->field_index= fieldnr;
936
&& !(f->unireg_check==Field::NEXT_NUMBER)
937
&& (f->flags & NOT_NULL_FLAG)
938
&& (f->real_type() != DRIZZLE_TYPE_TIMESTAMP))
939
f->flags|= NO_DEFAULT_VALUE_FLAG;
941
if (f->unireg_check == Field::NEXT_NUMBER)
942
share->found_next_number_field= &(share->field[fieldnr]);
944
if (share->timestamp_field == f)
945
share->timestamp_field_offset= fieldnr;
947
if (use_hash) /* supposedly this never fails... but comments lie */
948
(void) my_hash_insert(&share->name_hash,
949
(unsigned char*)&(share->field[fieldnr]));
953
keyinfo= share->key_info;
954
for (unsigned int keynr= 0; keynr < share->keys; keynr++, keyinfo++)
956
key_part= keyinfo->key_part;
958
for (unsigned int partnr= 0;
959
partnr < keyinfo->key_parts;
960
partnr++, key_part++)
962
/* Fix up key_part->offset by adding data_offset.
963
We really should compute offset as well.
964
But at least this way we are a little better. */
965
key_part->offset= field_offsets[key_part->fieldnr-1] + data_offset;
970
We need to set the unused bits to 1. If the number of bits is a multiple
971
of 8 there are no unused bits.
975
*(record + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
977
share->null_bytes= (null_pos - (unsigned char*) record +
978
(null_bit_pos + 7) / 8);
980
share->last_null_bit_pos= null_bit_pos;
983
free(field_pack_length);
985
if (!(handler_file= get_new_handler(share, session->mem_root,
990
if (share->key_parts)
992
uint32_t primary_key=(uint32_t) (find_type((char*) "PRIMARY",
993
&share->keynames, 3) - 1);
995
int64_t ha_option= handler_file->ha_table_flags();
997
keyinfo= share->key_info;
998
key_part= keyinfo->key_part;
1000
for (uint32_t key= 0 ; key < share->keys ; key++,keyinfo++)
1002
uint32_t usable_parts= 0;
1004
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1007
If the UNIQUE key doesn't have NULL columns and is not a part key
1008
declare this as a primary key.
1011
for (uint32_t i= 0 ; i < keyinfo->key_parts ;i++)
1013
uint32_t fieldnr= key_part[i].fieldnr;
1015
share->field[fieldnr-1]->null_ptr ||
1016
share->field[fieldnr-1]->key_length() !=
1019
primary_key=MAX_KEY; // Can't be used
1025
for (uint32_t i= 0 ; i < keyinfo->key_parts ; key_part++,i++)
1028
if (!key_part->fieldnr)
1030
// error= 4; // Wrong file
1031
abort(); // goto err;
1033
field= key_part->field= share->field[key_part->fieldnr-1];
1034
key_part->type= field->key_type();
1035
if (field->null_ptr)
1037
key_part->null_offset=(uint32_t) ((unsigned char*) field->null_ptr -
1038
share->default_values);
1039
key_part->null_bit= field->null_bit;
1040
key_part->store_length+=HA_KEY_NULL_LENGTH;
1041
keyinfo->flags|=HA_NULL_PART_KEY;
1042
keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
1043
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
1045
if (field->type() == DRIZZLE_TYPE_BLOB ||
1046
field->real_type() == DRIZZLE_TYPE_VARCHAR)
1048
if (field->type() == DRIZZLE_TYPE_BLOB)
1049
key_part->key_part_flag|= HA_BLOB_PART;
1051
key_part->key_part_flag|= HA_VAR_LENGTH_PART;
1052
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
1053
key_part->store_length+=HA_KEY_BLOB_LENGTH;
1054
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
1056
if (i == 0 && key != primary_key)
1057
field->flags |= (((keyinfo->flags & HA_NOSAME) &&
1058
(keyinfo->key_parts == 1)) ?
1059
UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
1061
field->key_start.set(key);
1062
if (field->key_length() == key_part->length &&
1063
!(field->flags & BLOB_FLAG))
1065
if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
1067
share->keys_for_keyread.set(key);
1068
field->part_of_key.set(key);
1069
field->part_of_key_not_clustered.set(key);
1071
if (handler_file->index_flags(key, i, 1) & HA_READ_ORDER)
1072
field->part_of_sortkey.set(key);
1074
if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
1076
usable_parts++; // For FILESORT
1077
field->flags|= PART_KEY_FLAG;
1078
if (key == primary_key)
1080
field->flags|= PRI_KEY_FLAG;
1082
If this field is part of the primary key and all keys contains
1083
the primary key, then we can use any key to find this column
1085
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
1087
field->part_of_key= share->keys_in_use;
1088
if (field->part_of_sortkey.test(key))
1089
field->part_of_sortkey= share->keys_in_use;
1092
if (field->key_length() != key_part->length)
1094
key_part->key_part_flag|= HA_PART_KEY_SEG;
1097
keyinfo->usable_key_parts= usable_parts; // Filesort
1099
set_if_bigger(share->max_key_length,keyinfo->key_length+
1100
keyinfo->key_parts);
1101
share->total_key_length+= keyinfo->key_length;
1103
MERGE tables do not have unique indexes. But every key could be
1104
an unique index on the underlying MyISAM table. (Bug #10400)
1106
if ((keyinfo->flags & HA_NOSAME) ||
1107
(ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
1108
set_if_bigger(share->max_unique_length,keyinfo->key_length);
1110
if (primary_key < MAX_KEY &&
1111
(share->keys_in_use.test(primary_key)))
1113
share->primary_key= primary_key;
1115
If we are using an integer as the primary key then allow the user to
1116
refer to it as '_rowid'
1118
if (share->key_info[primary_key].key_parts == 1)
1120
Field *field= share->key_info[primary_key].key_part[0].field;
1121
if (field && field->result_type() == INT_RESULT)
1123
/* note that fieldnr here (and rowid_field_offset) starts from 1 */
1124
share->rowid_field_offset= (share->key_info[primary_key].key_part[0].
1131
share->primary_key = MAX_KEY; // we do not have a primary key
1134
share->primary_key= MAX_KEY;
1136
if (share->found_next_number_field)
1138
Field *reg_field= *share->found_next_number_field;
1139
if ((int) (share->next_number_index= (uint32_t)
1140
find_ref_key(share->key_info, share->keys,
1141
share->default_values, reg_field,
1142
&share->next_number_key_offset,
1143
&share->next_number_keypart)) < 0)
1145
/* Wrong field definition */
1150
reg_field->flags |= AUTO_INCREMENT_FLAG;
1153
if (share->blob_fields)
1158
/* Store offsets to blob fields to find them fast */
1159
if (!(share->blob_field= save=
1160
(uint*) alloc_root(&share->mem_root,
1161
(uint32_t) (share->blob_fields* sizeof(uint32_t)))))
1163
for (k= 0, ptr= share->field ; *ptr ; ptr++, k++)
1165
if ((*ptr)->flags & BLOB_FLAG)
1170
share->db_low_byte_first= handler_file->low_byte_first();
1171
share->column_bitmap_size= bitmap_buffer_size(share->fields);
1173
my_bitmap_map *bitmaps;
1175
if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1176
share->column_bitmap_size)))
1178
bitmap_init(&share->all_set, bitmaps, share->fields);
1179
bitmap_set_all(&share->all_set);
1182
delete handler_file;
1186
share->error= error;
1187
share->open_errno= my_errno;
1189
hash_free(&share->name_hash);
1191
delete handler_file;
1192
share->open_table_error(error, share->open_errno, 0);
1198
Read table definition from a binary / text based .frm file
1202
session Thread handler
1203
share Fill this with table definition
1206
This function is called when the table definition is not cached in
1208
The data is returned in 'share', which is alloced by
1209
alloc_table_share().. The code assumes that share is initialized.
1213
1 Error (see open_table_error)
1214
2 Error (see open_table_error)
1215
3 Wrong data in .frm file
1216
4 Error (see open_table_error)
1217
5 Error (see open_table_error: charset unavailable)
1218
6 Unknown .frm version
1221
int open_table_def(Session *session, TableShare *share)
1229
drizzled::message::Table table;
1231
error= StorageEngine::getTableProto(share->normalized_path.str, &table);
1233
if (error != EEXIST)
1242
if (!table.IsInitialized())
1250
error= parse_table_proto(session, table, share);
1252
share->table_category= get_table_category(& share->db);
1255
session->status_var.opened_shares++;
1258
if (error && !error_given)
1260
share->error= error;
1261
share->open_table_error(error, (share->open_errno= my_errno), 0);
1269
Open a table based on a TableShare
1272
open_table_from_share()
1273
session Thread handler
1274
share Table definition
1275
alias Alias for table
1276
db_stat open flags (for example HA_OPEN_KEYFILE|
1277
HA_OPEN_RNDFILE..) can be 0 (example in
1279
prgflag READ_ALL etc..
1280
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
1281
outparam result table
1282
open_mode One of OTM_OPEN|OTM_CREATE|OTM_ALTER
1283
if OTM_CREATE some errors are ignore
1284
if OTM_ALTER HA_OPEN is not called
1288
1 Error (see open_table_error)
1289
2 Error (see open_table_error)
1290
3 Wrong data in .frm file
1291
4 Error (see open_table_error)
1292
5 Error (see open_table_error: charset unavailable)
1293
7 Table definition has changed in engine
1296
int open_table_from_share(Session *session, TableShare *share, const char *alias,
1297
uint32_t db_stat, uint32_t prgflag, uint32_t ha_open_flags,
1298
Table *outparam, open_table_mode open_mode)
1301
uint32_t records, i, bitmap_size;
1302
bool error_reported= false;
1303
unsigned char *record, *bitmaps;
1306
/* Parsing of partitioning information from .frm needs session->lex set up. */
1307
assert(session->lex->is_lex_started);
1310
outparam->resetTable(session, share, db_stat);
1313
if (!(outparam->alias= strdup(alias)))
1316
/* Allocate handler */
1317
if (!(prgflag & OPEN_FRM_FILE_ONLY))
1319
if (!(outparam->file= get_new_handler(share, &outparam->mem_root,
1330
if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
1332
if (prgflag & (READ_ALL+EXTRA_RECORD))
1335
if (!(record= (unsigned char*) alloc_root(&outparam->mem_root,
1336
share->rec_buff_length * records)))
1337
goto err; /* purecov: inspected */
1341
/* We are probably in hard repair, and the buffers should not be used */
1342
outparam->record[0]= outparam->record[1]= share->default_values;
1346
outparam->record[0]= record;
1348
outparam->record[1]= record+ share->rec_buff_length;
1350
outparam->record[1]= outparam->record[0]; // Safety
1355
We need this because when we read var-length rows, we are not updating
1356
bytes after end of varchar
1360
memcpy(outparam->record[0], share->default_values, share->rec_buff_length);
1361
memcpy(outparam->record[1], share->default_values, share->null_bytes);
1363
memcpy(outparam->record[1], share->default_values,
1364
share->rec_buff_length);
1368
if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root,
1369
(uint32_t) ((share->fields+1)*
1371
goto err; /* purecov: inspected */
1373
outparam->field= field_ptr;
1375
record= (unsigned char*) outparam->record[0]-1; /* Fieldstart = 1 */
1377
outparam->null_flags= (unsigned char*) record+1;
1379
/* Setup copy of fields from share, but use the right alias and record */
1380
for (i= 0 ; i < share->fields; i++, field_ptr++)
1382
if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam)))
1385
(*field_ptr)= 0; // End marker
1387
if (share->found_next_number_field)
1388
outparam->found_next_number_field=
1389
outparam->field[(uint32_t) (share->found_next_number_field - share->field)];
1390
if (share->timestamp_field)
1391
outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
1394
/* Fix key->name and key_part->field */
1395
if (share->key_parts)
1397
KEY *key_info, *key_info_end;
1398
KEY_PART_INFO *key_part;
1400
n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO);
1401
if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length)))
1403
outparam->key_info= key_info;
1404
key_part= (reinterpret_cast<KEY_PART_INFO*> (key_info+share->keys));
1406
memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
1407
memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) *
1410
for (key_info_end= key_info + share->keys ;
1411
key_info < key_info_end ;
1414
KEY_PART_INFO *key_part_end;
1416
key_info->table= outparam;
1417
key_info->key_part= key_part;
1419
for (key_part_end= key_part+ key_info->key_parts ;
1420
key_part < key_part_end ;
1423
Field *field= key_part->field= outparam->field[key_part->fieldnr-1];
1425
if (field->key_length() != key_part->length &&
1426
!(field->flags & BLOB_FLAG))
1429
We are using only a prefix of the column as a key:
1430
Create a new field for the key part that matches the index
1432
field= key_part->field=field->new_field(&outparam->mem_root,
1434
field->field_length= key_part->length;
1440
/* Allocate bitmaps */
1442
bitmap_size= share->column_bitmap_size;
1443
if (!(bitmaps= (unsigned char*) alloc_root(&outparam->mem_root, bitmap_size*3)))
1445
bitmap_init(&outparam->def_read_set,
1446
(my_bitmap_map*) bitmaps, share->fields);
1447
bitmap_init(&outparam->def_write_set,
1448
(my_bitmap_map*) (bitmaps+bitmap_size), share->fields);
1449
bitmap_init(&outparam->tmp_set,
1450
(my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields);
1451
outparam->default_column_bitmaps();
1453
/* The table struct is now initialized; Open the table */
1455
if (db_stat && open_mode != OTM_ALTER)
1458
if ((ha_err= (outparam->file->
1459
ha_open(outparam, share->normalized_path.str,
1460
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
1461
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
1462
(db_stat & HA_WAIT_IF_LOCKED) ? HA_OPEN_WAIT_IF_LOCKED :
1463
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
1464
HA_OPEN_ABORT_IF_LOCKED :
1465
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
1467
/* Set a flag if the table is crashed and it can be auto. repaired */
1468
share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
1469
outparam->file->auto_repair() &&
1470
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
1474
case HA_ERR_NO_SUCH_TABLE:
1476
The table did not exists in storage engine, use same error message
1477
as if the .frm file didn't exist
1484
Too many files opened, use same error message as if the .frm
1491
outparam->file->print_error(ha_err, MYF(0));
1492
error_reported= true;
1493
if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
1497
goto err; /* purecov: inspected */
1501
#if defined(HAVE_purify)
1502
memset(bitmaps, 0, bitmap_size*3);
1505
session->status_var.opened_tables++;
1510
if (!error_reported && !(prgflag & DONT_GIVE_ERROR))
1511
share->open_table_error(error, my_errno, 0);
1512
delete outparam->file;
1513
outparam->file= 0; // For easier error checking
1514
outparam->db_stat= 0;
1515
free_root(&outparam->mem_root, MYF(0)); // Safe to call on zeroed root
1516
free((char*) outparam->alias);
1521
Free information allocated by openfrm
1525
table Table object to free
1526
free_share Is 1 if we also want to free table_share
1529
int Table::closefrm(bool free_share)
82
error= cursor->close();
1534
error= file->close();
1535
free((char*) alias);
87
1539
for (Field **ptr=field ; *ptr ; ptr++)
94
cursor= 0; /* For easier errorchecking */
1544
file= 0; /* For easier errorchecking */
1547
if (s->tmp_table == NO_TMP_TABLE)
1548
TableShare::release(s);
1550
s->free_table_share();
1552
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)
127
db_stat= db_stat_arg;
129
record[0]= (unsigned char *) NULL;
130
record[1]= (unsigned char *) NULL;
132
insert_values.clear();
134
next_number_field= NULL;
135
found_next_number_field= NULL;
136
timestamp_field= NULL;
138
pos_in_table_list= NULL;
148
derived_select_number= 0;
149
current_lock= F_UNLCK;
163
open_placeholder= false;
164
locked_by_name= false;
167
auto_increment_field_not_null= false;
168
alias_name_used= false;
171
quick_condition_rows= 0;
173
timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
178
covering_keys.reset();
183
keys_in_use_for_query.reset();
184
keys_in_use_for_group_by.reset();
185
keys_in_use_for_order_by.reset();
187
memset(quick_rows, 0, sizeof(ha_rows) * MAX_KEY);
188
memset(const_key_parts, 0, sizeof(ha_rows) * MAX_KEY);
190
memset(quick_key_parts, 0, sizeof(unsigned int) * MAX_KEY);
191
memset(quick_n_ranges, 0, sizeof(unsigned int) * MAX_KEY);
193
memory::init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
198
1558
/* Deallocate temporary blob storage */
1398
2955
session->mem_root= mem_root_save;
2956
table->free_tmp_table(session); /* purecov: inspected */
2957
return NULL; /* purecov: inspected */
1404
2960
/****************************************************************************/
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;
2963
Create a reduced Table object with properly set up Field list from a
2964
list of field definitions.
2966
The created table doesn't have a table handler associated with
2967
it, has no keys, no group/distinct, no copy_funcs array.
2968
The sole purpose of this Table object is to use the power of Field
2969
class to read/write data to/from table->record[0]. Then one can store
2970
the record in any container (RB tree, hash, etc).
2971
The table is created in Session mem_root, so are the table's fields.
2972
Consequently, if you don't BLOB fields, you don't need to free it.
2974
@param session connection handle
2975
@param field_list list of column definitions
2978
0 if out of memory, Table object in case of success
2981
Table *create_virtual_tmp_table(Session *session, List<CreateField> &field_list)
2983
uint32_t field_count= field_list.elements;
2984
uint32_t blob_count= 0;
2986
CreateField *cdef; /* column definition */
2987
uint32_t record_length= 0;
2988
uint32_t null_count= 0; /* number of columns which may be null */
2989
uint32_t null_pack_length; /* NULL representation array length */
2990
uint32_t *blob_field;
2991
unsigned char *bitmaps;
2995
if (!multi_alloc_root(session->mem_root,
2996
&table, sizeof(*table),
2997
&share, sizeof(*share),
2998
&field, (field_count + 1) * sizeof(Field*),
2999
&blob_field, (field_count+1) *sizeof(uint32_t),
3000
&bitmaps, bitmap_buffer_size(field_count)*2,
3004
memset(table, 0, sizeof(*table));
3005
memset(share, 0, sizeof(*share));
3006
table->field= field;
3008
share->blob_field= blob_field;
3009
share->fields= field_count;
3010
share->blob_ptr_size= portable_sizeof_char_ptr;
3011
table->setup_tmp_table_column_bitmaps(bitmaps);
3013
/* Create all fields and calculate the total length of record */
3014
List_iterator_fast<CreateField> it(field_list);
3015
while ((cdef= it++))
3017
*field= make_field(share, NULL, 0, cdef->length,
3018
(unsigned char*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
3019
f_maybe_null(cdef->pack_flag) ? 1 : 0,
3020
cdef->pack_flag, cdef->sql_type, cdef->charset,
3022
cdef->interval, cdef->field_name);
3025
(*field)->init(table);
3026
record_length+= (*field)->pack_length();
3027
if (! ((*field)->flags & NOT_NULL_FLAG))
3030
if ((*field)->flags & BLOB_FLAG)
3031
share->blob_field[blob_count++]= (uint32_t) (field - table->field);
3035
*field= NULL; /* mark the end of the list */
3036
share->blob_field[blob_count]= 0; /* mark the end of the list */
3037
share->blob_fields= blob_count;
3039
null_pack_length= (null_count + 7)/8;
3040
share->reclength= record_length + null_pack_length;
3041
share->rec_buff_length= ALIGN_SIZE(share->reclength + 1);
3042
table->record[0]= (unsigned char*) session->alloc(share->rec_buff_length);
3043
if (!table->record[0])
3046
if (null_pack_length)
3048
table->null_flags= (unsigned char*) table->record[0];
3049
share->null_fields= null_count;
3050
share->null_bytes= null_pack_length;
3053
table->in_use= session; /* field->reset() may access table->in_use */
3055
/* Set up field pointers */
3056
unsigned char *null_pos= table->record[0];
3057
unsigned char *field_pos= null_pos + share->null_bytes;
3058
uint32_t null_bit= 1;
3060
for (field= table->field; *field; ++field)
3062
Field *cur_field= *field;
3063
if ((cur_field->flags & NOT_NULL_FLAG))
3064
cur_field->move_field(field_pos);
3067
cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
3069
if (null_bit == (1 << 8))
3077
field_pos+= cur_field->pack_length();
3082
for (field= table->field; *field; ++field)
3083
delete *field; /* just invokes field destructor */
3087
bool Table::open_tmp_table()
3090
if ((error=file->ha_open(this, s->table_name.str,O_RDWR,
3091
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
3093
file->print_error(error,MYF(0)); /* purecov: inspected */
3097
(void) file->extra(HA_EXTRA_QUICK); /* Faster */
3103
Create MyISAM temporary table
3106
create_myisam_tmp_table()
3107
keyinfo Description of the index (there is always one index)
3108
start_recinfo MyISAM's column descriptions
3109
recinfo INOUT End of MyISAM's column descriptions
3113
Create a MyISAM temporary table according to passed description. The is
3114
assumed to have one unique index or constraint.
3116
The passed array or MI_COLUMNDEF structures must have this form:
3118
1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
3119
when there are many nullable columns)
3121
3. One free MI_COLUMNDEF element (*recinfo points here)
3123
This function may use the free element to create hash column for unique
3131
bool Table::create_myisam_tmp_table(KEY *keyinfo,
3132
MI_COLUMNDEF *start_recinfo,
3133
MI_COLUMNDEF **recinfo,
3138
MI_UNIQUEDEF uniquedef;
3139
TableShare *share= s;
3142
{ // Get keys for ni_create
3143
bool using_unique_constraint= 0;
3144
HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&this->mem_root,
3145
sizeof(*seg) * keyinfo->key_parts);
3149
memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
3150
if (keyinfo->key_length >= file->max_key_length() ||
3151
keyinfo->key_parts > file->max_key_parts() ||
3154
/* Can't create a key; Make a unique constraint instead of a key */
3157
using_unique_constraint=1;
3158
memset(&uniquedef, 0, sizeof(uniquedef));
3159
uniquedef.keysegs=keyinfo->key_parts;
3161
uniquedef.null_are_equal=1;
3163
/* Create extra column for hash value */
3164
memset(*recinfo, 0, sizeof(**recinfo));
3165
(*recinfo)->type= FIELD_CHECK;
3166
(*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
3168
share->reclength+=MI_UNIQUE_HASH_LENGTH;
3172
/* Create an unique key */
3173
memset(&keydef, 0, sizeof(keydef));
3174
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
3175
keydef.keysegs= keyinfo->key_parts;
3178
for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
3180
Field *key_field=keyinfo->key_part[i].field;
3182
seg->language= key_field->charset()->number;
3183
seg->length= keyinfo->key_part[i].length;
3184
seg->start= keyinfo->key_part[i].offset;
3185
if (key_field->flags & BLOB_FLAG)
3188
((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
3189
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
3190
seg->bit_start= (uint8_t)(key_field->pack_length()
3191
- share->blob_ptr_size);
3192
seg->flag= HA_BLOB_PART;
3193
seg->length= 0; // Whole blob in unique constraint
3197
seg->type= keyinfo->key_part[i].type;
3199
if (!(key_field->flags & NOT_NULL_FLAG))
3201
seg->null_bit= key_field->null_bit;
3202
seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) record[0]);
3204
We are using a GROUP BY on something that contains NULL
3205
In this case we have to tell MyISAM that two NULL should
3206
on INSERT be regarded at the same value
3208
if (!using_unique_constraint)
3209
keydef.flag|= HA_NULL_ARE_EQUAL;
3213
MI_CREATE_INFO create_info;
3214
memset(&create_info, 0, sizeof(create_info));
3216
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
3218
create_info.data_file_length= ~(uint64_t) 0;
3220
if ((error=mi_create(share->table_name.str, share->keys, &keydef,
3221
(uint32_t) (*recinfo-start_recinfo),
3223
share->uniques, &uniquedef,
3225
HA_CREATE_TMP_TABLE)))
3227
file->print_error(error,MYF(0)); /* purecov: inspected */
3231
status_var_increment(in_use->status_var.created_tmp_disk_tables);
3232
share->db_record_offset= 1;
3239
void Table::free_tmp_table(Session *session)
3241
MEM_ROOT own_root= mem_root;
3242
const char *save_proc_info;
3244
save_proc_info=session->get_proc_info();
3245
session->set_proc_info("removing tmp table");
3247
// Release latches since this can take a long time
3248
ha_release_temporary_latches(session);
3253
file->ha_drop_table(s->table_name.str);
3255
s->db_type()->deleteTable(session, s->table_name.str);
3260
for (Field **ptr= field ; *ptr ; ptr++)
3264
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
3265
session->set_proc_info(save_proc_info);
3269
If a HEAP table gets full, create a MyISAM table and copy all rows
3273
bool create_myisam_from_heap(Session *session, Table *table,
3274
MI_COLUMNDEF *start_recinfo,
3275
MI_COLUMNDEF **recinfo,
3276
int error, bool ignore_last_dupp_key_error)
3280
const char *save_proc_info;
3283
if (table->s->db_type() != heap_engine ||
3284
error != HA_ERR_RECORD_FILE_FULL)
3286
table->file->print_error(error,MYF(0));
3290
// Release latches since this can take a long time
3291
ha_release_temporary_latches(session);
3295
new_table.s= &share;
3296
new_table.s->storage_engine= myisam_engine;
3297
if (!(new_table.file= get_new_handler(&share, &new_table.mem_root,
3298
new_table.s->db_type())))
3299
return true; // End of memory
3301
save_proc_info=session->get_proc_info();
3302
session->set_proc_info("converting HEAP to MyISAM");
3304
if (new_table.create_myisam_tmp_table(table->key_info, start_recinfo,
3305
recinfo, session->lex->select_lex.options |
3308
if (new_table.open_tmp_table())
3310
if (table->file->indexes_are_disabled())
3311
new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
3312
table->file->ha_index_or_rnd_end();
3313
table->file->ha_rnd_init(1);
3316
new_table.file->extra(HA_EXTRA_NO_ROWS);
3317
new_table.no_rows=1;
3320
/* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
3321
new_table.file->extra(HA_EXTRA_WRITE_CACHE);
3324
copy all old rows from heap table to MyISAM table
3325
This is the only code that uses record[1] to read/write but this
3326
is safe as this is a temporary MyISAM table without timestamp/autoincrement.
3328
while (!table->file->rnd_next(new_table.record[1]))
3330
write_err= new_table.file->ha_write_row(new_table.record[1]);
3334
/* copy row that filled HEAP table */
3335
if ((write_err=new_table.file->ha_write_row(table->record[0])))
3337
if (new_table.file->is_fatal_error(write_err, HA_CHECK_DUP) ||
3338
!ignore_last_dupp_key_error)
3342
/* remove heap table and change to use myisam table */
3343
(void) table->file->ha_rnd_end();
3344
(void) table->file->close(); // This deletes the table !
3347
new_table.s= table->s; // Keep old share
3351
table->file->change_table_ptr(table, table->s);
3352
table->use_all_columns();
3355
const char *new_proc_info=
3356
(!strcmp(save_proc_info,"Copying to tmp table") ?
3357
"Copying to tmp table on disk" : save_proc_info);
3358
session->set_proc_info(new_proc_info);
3363
table->file->print_error(write_err, MYF(0));
3364
(void) table->file->ha_rnd_end();
3365
(void) new_table.file->close();
3367
new_table.s->db_type()->deleteTable(session, new_table.s->table_name.str);
3369
delete new_table.file;
3370
session->set_proc_info(save_proc_info);
3371
table->mem_root= new_table.mem_root;
3375
my_bitmap_map *Table::use_all_columns(MY_BITMAP *bitmap)
3377
my_bitmap_map *old= bitmap->bitmap;
3378
bitmap->bitmap= s->all_set.bitmap;
1421
void Table::restore_column_map(const boost::dynamic_bitset<>& old)
3382
void Table::restore_column_map(my_bitmap_map *old)
1423
for (boost::dynamic_bitset<>::size_type i= 0; i < old.size(); i++)
3384
read_set->bitmap= old;
1436
3387
uint32_t Table::find_shortest_key(const key_map *usable_keys)