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
if (table_options.has_delay_key_write())
316
if (table_options.delay_key_write())
317
db_create_options|= HA_OPTION_DELAY_KEY_WRITE;
319
db_create_options|= HA_OPTION_NO_DELAY_KEY_WRITE;
322
/* db_create_options was stored as 2 bytes in FRM
323
Any HA_OPTION_ that doesn't fit into 2 bytes was silently truncated away.
325
share->db_create_options= (db_create_options & 0x0000FFFF);
326
share->db_options_in_use= share->db_create_options;
329
share->avg_row_length= table_options.has_avg_row_length() ?
330
table_options.avg_row_length() : 0;
332
share->page_checksum= table_options.has_page_checksum() ?
333
(table_options.page_checksum()?HA_CHOICE_YES:HA_CHOICE_NO)
336
share->row_type= table_options.has_row_type() ?
337
(enum row_type) table_options.row_type() : ROW_TYPE_DEFAULT;
339
share->block_size= table_options.has_block_size() ?
340
table_options.block_size() : 0;
342
share->table_charset= get_charset(table_options.has_collation_id()?
343
table_options.collation_id() : 0);
345
if (!share->table_charset)
347
/* unknown charset in head[38] or pre-3.23 frm */
348
if (use_mb(default_charset_info))
350
/* Warn that we may be changing the size of character columns */
351
errmsg_printf(ERRMSG_LVL_WARN,
352
_("'%s' had no or invalid character set, "
353
"and default character set is multi-byte, "
354
"so character column sizes may have changed"),
357
share->table_charset= default_charset_info;
360
share->db_record_offset= 1;
362
share->blob_ptr_size= portable_sizeof_char_ptr; // more bonghits.
364
share->db_low_byte_first= true;
366
share->max_rows= table_options.has_max_rows() ?
367
table_options.max_rows() : 0;
369
share->min_rows= table_options.has_min_rows() ?
370
table_options.min_rows() : 0;
372
share->keys= table.indexes_size();
375
for (int indx= 0; indx < table.indexes_size(); indx++)
376
share->key_parts+= table.indexes(indx).index_part_size();
378
share->key_info= (KEY*) alloc_root(&share->mem_root,
379
table.indexes_size() * sizeof(KEY)
380
+share->key_parts*sizeof(KEY_PART_INFO));
382
KEY_PART_INFO *key_part;
384
key_part= reinterpret_cast<KEY_PART_INFO*>
385
(share->key_info+table.indexes_size());
388
ulong *rec_per_key= (ulong*) alloc_root(&share->mem_root,
389
sizeof(ulong*)*share->key_parts);
391
share->keynames.count= table.indexes_size();
392
share->keynames.name= NULL;
393
share->keynames.type_names= (const char**)
394
alloc_root(&share->mem_root, sizeof(char*) * (table.indexes_size()+1));
396
share->keynames.type_lengths= (unsigned int*)
397
alloc_root(&share->mem_root,
398
sizeof(unsigned int) * (table.indexes_size()+1));
400
share->keynames.type_names[share->keynames.count]= NULL;
401
share->keynames.type_lengths[share->keynames.count]= 0;
403
KEY* keyinfo= share->key_info;
404
for (int keynr= 0; keynr < table.indexes_size(); keynr++, keyinfo++)
406
drizzled::message::Table::Index indx= table.indexes(keynr);
411
if (indx.is_unique())
412
keyinfo->flags|= HA_NOSAME;
414
if (indx.has_options())
416
drizzled::message::Table::Index::IndexOptions indx_options= indx.options();
417
if (indx_options.pack_key())
418
keyinfo->flags|= HA_PACK_KEY;
420
if (indx_options.var_length_key())
421
keyinfo->flags|= HA_VAR_LENGTH_PART;
423
if (indx_options.null_part_key())
424
keyinfo->flags|= HA_NULL_PART_KEY;
426
if (indx_options.binary_pack_key())
427
keyinfo->flags|= HA_BINARY_PACK_KEY;
429
if (indx_options.has_partial_segments())
430
keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
432
if (indx_options.auto_generated_key())
433
keyinfo->flags|= HA_GENERATED_KEY;
435
if (indx_options.has_key_block_size())
437
keyinfo->flags|= HA_USES_BLOCK_SIZE;
438
keyinfo->block_size= indx_options.key_block_size();
442
keyinfo->block_size= 0;
449
case drizzled::message::Table::Index::UNKNOWN_INDEX:
450
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
452
case drizzled::message::Table::Index::BTREE:
453
keyinfo->algorithm= HA_KEY_ALG_BTREE;
455
case drizzled::message::Table::Index::RTREE:
456
keyinfo->algorithm= HA_KEY_ALG_RTREE;
458
case drizzled::message::Table::Index::HASH:
459
keyinfo->algorithm= HA_KEY_ALG_HASH;
461
case drizzled::message::Table::Index::FULLTEXT:
462
keyinfo->algorithm= HA_KEY_ALG_FULLTEXT;
465
/* TODO: suitable warning ? */
466
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
470
keyinfo->key_length= indx.key_length();
472
keyinfo->key_parts= indx.index_part_size();
474
keyinfo->key_part= key_part;
475
keyinfo->rec_per_key= rec_per_key;
477
for (unsigned int partnr= 0;
478
partnr < keyinfo->key_parts;
479
partnr++, key_part++)
481
drizzled::message::Table::Index::IndexPart part;
482
part= indx.index_part(partnr);
486
key_part->field= NULL;
487
key_part->fieldnr= part.fieldnr() + 1; // start from 1.
488
key_part->null_bit= 0;
489
/* key_part->null_offset is only set if null_bit (see later) */
490
/* key_part->key_type= */ /* I *THINK* this may be okay.... */
491
/* key_part->type ???? */
492
key_part->key_part_flag= 0;
493
if (part.has_in_reverse_order())
494
key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
496
key_part->length= part.compare_length();
498
key_part->store_length= key_part->length;
500
/* key_part->offset is set later */
501
key_part->key_type= part.key_type();
505
if (!indx.has_comment())
507
keyinfo->comment.length= 0;
508
keyinfo->comment.str= NULL;
512
keyinfo->flags|= HA_USES_COMMENT;
513
keyinfo->comment.length= indx.comment().length();
514
keyinfo->comment.str= strmake_root(&share->mem_root,
515
indx.comment().c_str(),
516
keyinfo->comment.length);
519
keyinfo->name= strmake_root(&share->mem_root,
521
indx.name().length());
523
share->keynames.type_names[keynr]= keyinfo->name;
524
share->keynames.type_lengths[keynr]= indx.name().length();
527
share->keys_for_keyread.reset();
528
set_prefix(share->keys_in_use, share->keys);
530
if (table_options.has_connect_string())
532
size_t len= table_options.connect_string().length();
533
const char* str= table_options.connect_string().c_str();
535
share->connect_string.length= len;
536
share->connect_string.str= strmake_root(&share->mem_root, str, len);
539
if (table_options.has_comment())
541
size_t len= table_options.comment().length();
542
const char* str= table_options.comment().c_str();
544
share->comment.length= len;
545
share->comment.str= strmake_root(&share->mem_root, str, len);
548
share->key_block_size= table_options.has_key_block_size() ?
549
table_options.key_block_size() : 0;
551
share->fields= table.field_size();
553
share->field= (Field**) alloc_root(&share->mem_root,
554
((share->fields+1) * sizeof(Field*)));
555
share->field[share->fields]= NULL;
557
uint32_t null_fields= 0;
560
uint32_t *field_offsets= (uint32_t*)malloc(share->fields * sizeof(uint32_t));
561
uint32_t *field_pack_length=(uint32_t*)malloc(share->fields*sizeof(uint32_t));
563
assert(field_offsets && field_pack_length); // TODO: fixme
565
uint32_t interval_count= 0;
566
uint32_t interval_parts= 0;
568
uint32_t stored_columns_reclength= 0;
570
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
572
drizzled::message::Table::Field pfield= table.field(fieldnr);
573
if (pfield.has_constraints() && pfield.constraints().is_nullable())
576
enum_field_types drizzle_field_type=
577
proto_field_type_to_drizzle_type(pfield.type());
579
field_offsets[fieldnr]= stored_columns_reclength;
581
/* the below switch is very similar to
582
CreateField::create_length_to_internal_length in field.cc
583
(which should one day be replace by just this code)
585
switch(drizzle_field_type)
587
case DRIZZLE_TYPE_BLOB:
588
case DRIZZLE_TYPE_VARCHAR:
590
drizzled::message::Table::Field::StringFieldOptions field_options=
591
pfield.string_options();
593
const CHARSET_INFO *cs= get_charset(field_options.has_collation_id()?
594
field_options.collation_id() : 0);
597
cs= default_charset_info;
599
field_pack_length[fieldnr]=
600
calc_pack_length(drizzle_field_type,
601
field_options.length() * cs->mbmaxlen);
605
case DRIZZLE_TYPE_ENUM:
607
drizzled::message::Table::Field::SetFieldOptions field_options=
608
pfield.set_options();
610
field_pack_length[fieldnr]=
611
get_enum_pack_length(field_options.field_value_size());
614
interval_parts+= field_options.field_value_size();
617
case DRIZZLE_TYPE_NEWDECIMAL:
619
drizzled::message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
621
field_pack_length[fieldnr]=
622
my_decimal_get_binary_size(fo.precision(), fo.scale());
626
/* Zero is okay here as length is fixed for other types. */
627
field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
630
share->reclength+= field_pack_length[fieldnr];
631
stored_columns_reclength+= field_pack_length[fieldnr];
635
/* data_offset added to stored_rec_length later */
636
share->stored_rec_length= stored_columns_reclength;
638
share->null_fields= null_fields;
640
ulong null_bits= null_fields;
641
if (!table_options.pack_record())
643
ulong data_offset= (null_bits + 7)/8;
646
share->reclength+= data_offset;
647
share->stored_rec_length+= data_offset;
649
ulong rec_buff_length;
651
rec_buff_length= ALIGN_SIZE(share->reclength + 1);
652
share->rec_buff_length= rec_buff_length;
654
unsigned char* record= NULL;
656
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
660
memset(record, 0, rec_buff_length);
664
if (!table_options.pack_record())
666
null_count++; // one bit for delete mark.
670
share->default_values= record;
674
share->intervals= (TYPELIB*)alloc_root(&share->mem_root,
675
interval_count*sizeof(TYPELIB));
678
share->intervals= NULL;
680
share->fieldnames.type_names= (const char**)alloc_root(&share->mem_root,
681
(share->fields+1)*sizeof(char*));
683
share->fieldnames.type_lengths= (unsigned int*) alloc_root(&share->mem_root,
684
(share->fields+1)*sizeof(unsigned int));
686
share->fieldnames.type_names[share->fields]= NULL;
687
share->fieldnames.type_lengths[share->fields]= 0;
688
share->fieldnames.count= share->fields;
691
/* Now fix the TYPELIBs for the intervals (enum values)
695
uint32_t interval_nr= 0;
697
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
699
drizzled::message::Table::Field pfield= table.field(fieldnr);
702
share->fieldnames.type_names[fieldnr]= strmake_root(&share->mem_root,
703
pfield.name().c_str(),
704
pfield.name().length());
706
share->fieldnames.type_lengths[fieldnr]= pfield.name().length();
709
if (pfield.type() != drizzled::message::Table::Field::ENUM)
712
drizzled::message::Table::Field::SetFieldOptions field_options=
713
pfield.set_options();
715
const CHARSET_INFO *charset= get_charset(field_options.has_collation_id()?
716
field_options.collation_id() : 0);
719
charset= default_charset_info;
721
TYPELIB *t= &(share->intervals[interval_nr]);
723
t->type_names= (const char**)alloc_root(&share->mem_root,
724
(field_options.field_value_size()+1)*sizeof(char*));
726
t->type_lengths= (unsigned int*) alloc_root(&share->mem_root,
727
(field_options.field_value_size()+1)*sizeof(unsigned int));
729
t->type_names[field_options.field_value_size()]= NULL;
730
t->type_lengths[field_options.field_value_size()]= 0;
732
t->count= field_options.field_value_size();
735
for (int n= 0; n < field_options.field_value_size(); n++)
737
t->type_names[n]= strmake_root(&share->mem_root,
738
field_options.field_value(n).c_str(),
739
field_options.field_value(n).length());
741
/* Go ask the charset what the length is as for "" length=1
742
and there's stripping spaces or some other crack going on.
745
lengthsp= charset->cset->lengthsp(charset, t->type_names[n],
746
field_options.field_value(n).length());
747
t->type_lengths[n]= lengthsp;
753
/* and read the fields */
756
bool use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
759
use_hash= !hash_init(&share->name_hash,
762
(hash_get_key) get_field_name, 0, 0);
764
unsigned char* null_pos= record;;
765
int null_bit_pos= (table_options.pack_record()) ? 0 : 1;
767
for (unsigned int fieldnr= 0; fieldnr < share->fields; fieldnr++)
769
drizzled::message::Table::Field pfield= table.field(fieldnr);
771
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
773
switch(pfield.format())
775
case drizzled::message::Table::Field::DefaultFormat:
776
column_format= COLUMN_FORMAT_TYPE_DEFAULT;
778
case drizzled::message::Table::Field::FixedFormat:
779
column_format= COLUMN_FORMAT_TYPE_FIXED;
781
case drizzled::message::Table::Field::DynamicFormat:
782
column_format= COLUMN_FORMAT_TYPE_DYNAMIC;
788
Field::utype unireg_type= Field::NONE;
790
if (pfield.has_numeric_options()
791
&& pfield.numeric_options().is_autoincrement())
793
unireg_type= Field::NEXT_NUMBER;
796
if (pfield.has_options()
797
&& pfield.options().has_default_value()
798
&& pfield.options().default_value().compare("NOW()") == 0)
800
if (pfield.options().has_update_value()
801
&& pfield.options().update_value().compare("NOW()") == 0)
803
unireg_type= Field::TIMESTAMP_DNUN_FIELD;
805
else if (!pfield.options().has_update_value())
807
unireg_type= Field::TIMESTAMP_DN_FIELD;
810
assert(1); // Invalid update value.
812
else if (pfield.has_options()
813
&& pfield.options().has_update_value()
814
&& pfield.options().update_value().compare("NOW()") == 0)
816
unireg_type= Field::TIMESTAMP_UN_FIELD;
820
if (!pfield.has_comment())
822
comment.str= (char*)"";
827
size_t len= pfield.comment().length();
828
const char* str= pfield.comment().c_str();
830
comment.str= strmake_root(&share->mem_root, str, len);
834
enum_field_types field_type;
836
field_type= proto_field_type_to_drizzle_type(pfield.type());
838
const CHARSET_INFO *charset= &my_charset_bin;
840
if (field_type==DRIZZLE_TYPE_BLOB
841
|| field_type==DRIZZLE_TYPE_VARCHAR)
843
drizzled::message::Table::Field::StringFieldOptions field_options=
844
pfield.string_options();
846
charset= get_charset(field_options.has_collation_id()?
847
field_options.collation_id() : 0);
850
charset= default_charset_info;
854
if (field_type==DRIZZLE_TYPE_ENUM)
856
drizzled::message::Table::Field::SetFieldOptions field_options=
857
pfield.set_options();
859
charset= get_charset(field_options.has_collation_id()?
860
field_options.collation_id() : 0);
863
charset= default_charset_info;
867
Item *default_value= NULL;
869
if (pfield.options().has_default_value()
870
|| pfield.options().has_default_null()
871
|| pfield.options().has_default_bin_value())
873
default_value= default_value_item(field_type,
875
pfield.options().default_null(),
876
&pfield.options().default_value(),
877
&pfield.options().default_bin_value());
880
uint32_t pack_flag= pfield.pack_flag(); /* TODO: MUST DIE */
882
Table temp_table; /* Use this so that BLOB DEFAULT '' works */
883
memset(&temp_table, 0, sizeof(temp_table));
885
temp_table.in_use= session;
886
temp_table.s->db_low_byte_first= 1; //handler->low_byte_first();
887
temp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
889
Field* f= make_field(share, &share->mem_root,
890
record+field_offsets[fieldnr]+data_offset,
891
pfield.options().length(),
897
(Field::utype) MTYP_TYPENR(unireg_type),
898
((field_type==DRIZZLE_TYPE_ENUM)?
899
share->intervals+(interval_nr++)
901
share->fieldnames.type_names[fieldnr]);
903
share->field[fieldnr]= f;
905
f->init(&temp_table); /* blob default values need table obj */
907
if (!(f->flags & NOT_NULL_FLAG))
909
*f->null_ptr|= f->null_bit;
910
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
917
enum_check_fields old_count_cuted_fields= session->count_cuted_fields;
918
session->count_cuted_fields= CHECK_FIELD_WARN;
919
int res= default_value->save_in_field(f, 1);
920
session->count_cuted_fields= old_count_cuted_fields;
921
if (res != 0 && res != 3)
923
my_error(ER_INVALID_DEFAULT, MYF(0), f->field_name);
928
else if (f->real_type() == DRIZZLE_TYPE_ENUM &&
929
(f->flags & NOT_NULL_FLAG))
932
f->store((int64_t) 1, true);
937
/* hack to undo f->init() */
941
f->field_index= fieldnr;
944
&& !(f->unireg_check==Field::NEXT_NUMBER)
945
&& (f->flags & NOT_NULL_FLAG)
946
&& (f->real_type() != DRIZZLE_TYPE_TIMESTAMP))
947
f->flags|= NO_DEFAULT_VALUE_FLAG;
949
if (f->unireg_check == Field::NEXT_NUMBER)
950
share->found_next_number_field= &(share->field[fieldnr]);
952
if (share->timestamp_field == f)
953
share->timestamp_field_offset= fieldnr;
955
if (use_hash) /* supposedly this never fails... but comments lie */
956
(void) my_hash_insert(&share->name_hash,
957
(unsigned char*)&(share->field[fieldnr]));
961
keyinfo= share->key_info;
962
for (unsigned int keynr= 0; keynr < share->keys; keynr++, keyinfo++)
964
key_part= keyinfo->key_part;
966
for (unsigned int partnr= 0;
967
partnr < keyinfo->key_parts;
968
partnr++, key_part++)
970
/* Fix up key_part->offset by adding data_offset.
971
We really should compute offset as well.
972
But at least this way we are a little better. */
973
key_part->offset= field_offsets[key_part->fieldnr-1] + data_offset;
978
We need to set the unused bits to 1. If the number of bits is a multiple
979
of 8 there are no unused bits.
983
*(record + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
985
share->null_bytes= (null_pos - (unsigned char*) record +
986
(null_bit_pos + 7) / 8);
988
share->last_null_bit_pos= null_bit_pos;
991
free(field_pack_length);
993
if (!(handler_file= get_new_handler(share, session->mem_root,
998
if (share->key_parts)
1000
uint32_t primary_key=(uint32_t) (find_type((char*) "PRIMARY",
1001
&share->keynames, 3) - 1);
1003
int64_t ha_option= handler_file->ha_table_flags();
1005
keyinfo= share->key_info;
1006
key_part= keyinfo->key_part;
1008
for (uint32_t key= 0 ; key < share->keys ; key++,keyinfo++)
1010
uint32_t usable_parts= 0;
1012
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1015
If the UNIQUE key doesn't have NULL columns and is not a part key
1016
declare this as a primary key.
1019
for (uint32_t i= 0 ; i < keyinfo->key_parts ;i++)
1021
uint32_t fieldnr= key_part[i].fieldnr;
1023
share->field[fieldnr-1]->null_ptr ||
1024
share->field[fieldnr-1]->key_length() !=
1027
primary_key=MAX_KEY; // Can't be used
1033
for (uint32_t i= 0 ; i < keyinfo->key_parts ; key_part++,i++)
1036
if (!key_part->fieldnr)
1038
// error= 4; // Wrong file
1039
abort(); // goto err;
1041
field= key_part->field= share->field[key_part->fieldnr-1];
1042
key_part->type= field->key_type();
1043
if (field->null_ptr)
1045
key_part->null_offset=(uint32_t) ((unsigned char*) field->null_ptr -
1046
share->default_values);
1047
key_part->null_bit= field->null_bit;
1048
key_part->store_length+=HA_KEY_NULL_LENGTH;
1049
keyinfo->flags|=HA_NULL_PART_KEY;
1050
keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
1051
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
1053
if (field->type() == DRIZZLE_TYPE_BLOB ||
1054
field->real_type() == DRIZZLE_TYPE_VARCHAR)
1056
if (field->type() == DRIZZLE_TYPE_BLOB)
1057
key_part->key_part_flag|= HA_BLOB_PART;
1059
key_part->key_part_flag|= HA_VAR_LENGTH_PART;
1060
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
1061
key_part->store_length+=HA_KEY_BLOB_LENGTH;
1062
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
1064
if (i == 0 && key != primary_key)
1065
field->flags |= (((keyinfo->flags & HA_NOSAME) &&
1066
(keyinfo->key_parts == 1)) ?
1067
UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
1069
field->key_start.set(key);
1070
if (field->key_length() == key_part->length &&
1071
!(field->flags & BLOB_FLAG))
1073
if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
1075
share->keys_for_keyread.set(key);
1076
field->part_of_key.set(key);
1077
field->part_of_key_not_clustered.set(key);
1079
if (handler_file->index_flags(key, i, 1) & HA_READ_ORDER)
1080
field->part_of_sortkey.set(key);
1082
if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
1084
usable_parts++; // For FILESORT
1085
field->flags|= PART_KEY_FLAG;
1086
if (key == primary_key)
1088
field->flags|= PRI_KEY_FLAG;
1090
If this field is part of the primary key and all keys contains
1091
the primary key, then we can use any key to find this column
1093
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
1095
field->part_of_key= share->keys_in_use;
1096
if (field->part_of_sortkey.test(key))
1097
field->part_of_sortkey= share->keys_in_use;
1100
if (field->key_length() != key_part->length)
1102
key_part->key_part_flag|= HA_PART_KEY_SEG;
1105
keyinfo->usable_key_parts= usable_parts; // Filesort
1107
set_if_bigger(share->max_key_length,keyinfo->key_length+
1108
keyinfo->key_parts);
1109
share->total_key_length+= keyinfo->key_length;
1111
MERGE tables do not have unique indexes. But every key could be
1112
an unique index on the underlying MyISAM table. (Bug #10400)
1114
if ((keyinfo->flags & HA_NOSAME) ||
1115
(ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
1116
set_if_bigger(share->max_unique_length,keyinfo->key_length);
1118
if (primary_key < MAX_KEY &&
1119
(share->keys_in_use.test(primary_key)))
1121
share->primary_key= primary_key;
1123
If we are using an integer as the primary key then allow the user to
1124
refer to it as '_rowid'
1126
if (share->key_info[primary_key].key_parts == 1)
1128
Field *field= share->key_info[primary_key].key_part[0].field;
1129
if (field && field->result_type() == INT_RESULT)
1131
/* note that fieldnr here (and rowid_field_offset) starts from 1 */
1132
share->rowid_field_offset= (share->key_info[primary_key].key_part[0].
1139
share->primary_key = MAX_KEY; // we do not have a primary key
1142
share->primary_key= MAX_KEY;
1144
if (share->found_next_number_field)
1146
Field *reg_field= *share->found_next_number_field;
1147
if ((int) (share->next_number_index= (uint32_t)
1148
find_ref_key(share->key_info, share->keys,
1149
share->default_values, reg_field,
1150
&share->next_number_key_offset,
1151
&share->next_number_keypart)) < 0)
1153
/* Wrong field definition */
1158
reg_field->flags |= AUTO_INCREMENT_FLAG;
1161
if (share->blob_fields)
1166
/* Store offsets to blob fields to find them fast */
1167
if (!(share->blob_field= save=
1168
(uint*) alloc_root(&share->mem_root,
1169
(uint32_t) (share->blob_fields* sizeof(uint32_t)))))
1171
for (k= 0, ptr= share->field ; *ptr ; ptr++, k++)
1173
if ((*ptr)->flags & BLOB_FLAG)
1178
share->db_low_byte_first= handler_file->low_byte_first();
1179
share->column_bitmap_size= bitmap_buffer_size(share->fields);
1181
my_bitmap_map *bitmaps;
1183
if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1184
share->column_bitmap_size)))
1186
bitmap_init(&share->all_set, bitmaps, share->fields);
1187
bitmap_set_all(&share->all_set);
1190
delete handler_file;
1194
share->error= error;
1195
share->open_errno= my_errno;
1197
hash_free(&share->name_hash);
1199
delete handler_file;
1200
share->open_table_error(error, share->open_errno, 0);
1206
Read table definition from a binary / text based .frm file
1210
session Thread handler
1211
share Fill this with table definition
1214
This function is called when the table definition is not cached in
1216
The data is returned in 'share', which is alloced by
1217
alloc_table_share().. The code assumes that share is initialized.
1221
1 Error (see open_table_error)
1222
2 Error (see open_table_error)
1223
3 Wrong data in .frm file
1224
4 Error (see open_table_error)
1225
5 Error (see open_table_error: charset unavailable)
1226
6 Unknown .frm version
1229
int open_table_def(Session *session, TableShare *share)
1237
drizzled::message::Table table;
1239
error= StorageEngine::getTableProto(share->normalized_path.str, &table);
1241
if (error != EEXIST)
1250
if (!table.IsInitialized())
1258
error= parse_table_proto(session, table, share);
1260
share->table_category= get_table_category(& share->db);
1263
session->status_var.opened_shares++;
1266
if (error && !error_given)
1268
share->error= error;
1269
share->open_table_error(error, (share->open_errno= my_errno), 0);
1277
Open a table based on a TableShare
1280
open_table_from_share()
1281
session Thread handler
1282
share Table definition
1283
alias Alias for table
1284
db_stat open flags (for example HA_OPEN_KEYFILE|
1285
HA_OPEN_RNDFILE..) can be 0 (example in
1287
prgflag READ_ALL etc..
1288
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
1289
outparam result table
1290
open_mode One of OTM_OPEN|OTM_CREATE|OTM_ALTER
1291
if OTM_CREATE some errors are ignore
1292
if OTM_ALTER HA_OPEN is not called
1296
1 Error (see open_table_error)
1297
2 Error (see open_table_error)
1298
3 Wrong data in .frm file
1299
4 Error (see open_table_error)
1300
5 Error (see open_table_error: charset unavailable)
1301
7 Table definition has changed in engine
1304
int open_table_from_share(Session *session, TableShare *share, const char *alias,
1305
uint32_t db_stat, uint32_t prgflag, uint32_t ha_open_flags,
1306
Table *outparam, open_table_mode open_mode)
1309
uint32_t records, i, bitmap_size;
1310
bool error_reported= false;
1311
unsigned char *record, *bitmaps;
1314
/* Parsing of partitioning information from .frm needs session->lex set up. */
1315
assert(session->lex->is_lex_started);
1318
outparam->resetTable(session, share, db_stat);
1321
if (!(outparam->alias= strdup(alias)))
1324
/* Allocate handler */
1325
if (!(prgflag & OPEN_FRM_FILE_ONLY))
1327
if (!(outparam->file= get_new_handler(share, &outparam->mem_root,
1338
if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
1340
if (prgflag & (READ_ALL+EXTRA_RECORD))
1343
if (!(record= (unsigned char*) alloc_root(&outparam->mem_root,
1344
share->rec_buff_length * records)))
1345
goto err; /* purecov: inspected */
1349
/* We are probably in hard repair, and the buffers should not be used */
1350
outparam->record[0]= outparam->record[1]= share->default_values;
1354
outparam->record[0]= record;
1356
outparam->record[1]= record+ share->rec_buff_length;
1358
outparam->record[1]= outparam->record[0]; // Safety
1363
We need this because when we read var-length rows, we are not updating
1364
bytes after end of varchar
1368
memcpy(outparam->record[0], share->default_values, share->rec_buff_length);
1369
memcpy(outparam->record[1], share->default_values, share->null_bytes);
1371
memcpy(outparam->record[1], share->default_values,
1372
share->rec_buff_length);
1376
if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root,
1377
(uint32_t) ((share->fields+1)*
1379
goto err; /* purecov: inspected */
1381
outparam->field= field_ptr;
1383
record= (unsigned char*) outparam->record[0]-1; /* Fieldstart = 1 */
1385
outparam->null_flags= (unsigned char*) record+1;
1387
/* Setup copy of fields from share, but use the right alias and record */
1388
for (i= 0 ; i < share->fields; i++, field_ptr++)
1390
if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam)))
1393
(*field_ptr)= 0; // End marker
1395
if (share->found_next_number_field)
1396
outparam->found_next_number_field=
1397
outparam->field[(uint32_t) (share->found_next_number_field - share->field)];
1398
if (share->timestamp_field)
1399
outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
1402
/* Fix key->name and key_part->field */
1403
if (share->key_parts)
1405
KEY *key_info, *key_info_end;
1406
KEY_PART_INFO *key_part;
1408
n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO);
1409
if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length)))
1411
outparam->key_info= key_info;
1412
key_part= (reinterpret_cast<KEY_PART_INFO*> (key_info+share->keys));
1414
memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
1415
memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) *
1418
for (key_info_end= key_info + share->keys ;
1419
key_info < key_info_end ;
1422
KEY_PART_INFO *key_part_end;
1424
key_info->table= outparam;
1425
key_info->key_part= key_part;
1427
for (key_part_end= key_part+ key_info->key_parts ;
1428
key_part < key_part_end ;
1431
Field *field= key_part->field= outparam->field[key_part->fieldnr-1];
1433
if (field->key_length() != key_part->length &&
1434
!(field->flags & BLOB_FLAG))
1437
We are using only a prefix of the column as a key:
1438
Create a new field for the key part that matches the index
1440
field= key_part->field=field->new_field(&outparam->mem_root,
1442
field->field_length= key_part->length;
1448
/* Allocate bitmaps */
1450
bitmap_size= share->column_bitmap_size;
1451
if (!(bitmaps= (unsigned char*) alloc_root(&outparam->mem_root, bitmap_size*3)))
1453
bitmap_init(&outparam->def_read_set,
1454
(my_bitmap_map*) bitmaps, share->fields);
1455
bitmap_init(&outparam->def_write_set,
1456
(my_bitmap_map*) (bitmaps+bitmap_size), share->fields);
1457
bitmap_init(&outparam->tmp_set,
1458
(my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields);
1459
outparam->default_column_bitmaps();
1461
/* The table struct is now initialized; Open the table */
1463
if (db_stat && open_mode != OTM_ALTER)
1466
if ((ha_err= (outparam->file->
1467
ha_open(outparam, share->normalized_path.str,
1468
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
1469
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
1470
(db_stat & HA_WAIT_IF_LOCKED) ? HA_OPEN_WAIT_IF_LOCKED :
1471
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
1472
HA_OPEN_ABORT_IF_LOCKED :
1473
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
1475
/* Set a flag if the table is crashed and it can be auto. repaired */
1476
share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
1477
outparam->file->auto_repair() &&
1478
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
1482
case HA_ERR_NO_SUCH_TABLE:
1484
The table did not exists in storage engine, use same error message
1485
as if the .frm file didn't exist
1492
Too many files opened, use same error message as if the .frm
1499
outparam->file->print_error(ha_err, MYF(0));
1500
error_reported= true;
1501
if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
1505
goto err; /* purecov: inspected */
1509
#if defined(HAVE_purify)
1510
memset(bitmaps, 0, bitmap_size*3);
1513
session->status_var.opened_tables++;
1518
if (!error_reported && !(prgflag & DONT_GIVE_ERROR))
1519
share->open_table_error(error, my_errno, 0);
1520
delete outparam->file;
1521
outparam->file= 0; // For easier error checking
1522
outparam->db_stat= 0;
1523
free_root(&outparam->mem_root, MYF(0)); // Safe to call on zeroed root
1524
free((char*) outparam->alias);
1529
Free information allocated by openfrm
1533
table Table object to free
1534
free_share Is 1 if we also want to free table_share
1537
int Table::closefrm(bool free_share)
82
error= cursor->close();
1542
error= file->close();
1543
free((char*) alias);
87
1547
for (Field **ptr=field ; *ptr ; ptr++)
94
cursor= 0; /* For easier errorchecking */
1552
file= 0; /* For easier errorchecking */
1555
if (s->tmp_table == NO_TMP_TABLE)
1556
TableShare::release(s);
1558
s->free_table_share();
1560
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
1566
/* Deallocate temporary blob storage */
1398
2962
session->mem_root= mem_root_save;
2963
table->free_tmp_table(session); /* purecov: inspected */
2964
return NULL; /* purecov: inspected */
1404
2967
/****************************************************************************/
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;
2970
Create a reduced Table object with properly set up Field list from a
2971
list of field definitions.
2973
The created table doesn't have a table handler associated with
2974
it, has no keys, no group/distinct, no copy_funcs array.
2975
The sole purpose of this Table object is to use the power of Field
2976
class to read/write data to/from table->record[0]. Then one can store
2977
the record in any container (RB tree, hash, etc).
2978
The table is created in Session mem_root, so are the table's fields.
2979
Consequently, if you don't BLOB fields, you don't need to free it.
2981
@param session connection handle
2982
@param field_list list of column definitions
2985
0 if out of memory, Table object in case of success
2988
Table *create_virtual_tmp_table(Session *session, List<CreateField> &field_list)
2990
uint32_t field_count= field_list.elements;
2991
uint32_t blob_count= 0;
2993
CreateField *cdef; /* column definition */
2994
uint32_t record_length= 0;
2995
uint32_t null_count= 0; /* number of columns which may be null */
2996
uint32_t null_pack_length; /* NULL representation array length */
2997
uint32_t *blob_field;
2998
unsigned char *bitmaps;
3002
if (!multi_alloc_root(session->mem_root,
3003
&table, sizeof(*table),
3004
&share, sizeof(*share),
3005
&field, (field_count + 1) * sizeof(Field*),
3006
&blob_field, (field_count+1) *sizeof(uint32_t),
3007
&bitmaps, bitmap_buffer_size(field_count)*2,
3011
memset(table, 0, sizeof(*table));
3012
memset(share, 0, sizeof(*share));
3013
table->field= field;
3015
share->blob_field= blob_field;
3016
share->fields= field_count;
3017
share->blob_ptr_size= portable_sizeof_char_ptr;
3018
table->setup_tmp_table_column_bitmaps(bitmaps);
3020
/* Create all fields and calculate the total length of record */
3021
List_iterator_fast<CreateField> it(field_list);
3022
while ((cdef= it++))
3024
*field= make_field(share, NULL, 0, cdef->length,
3025
(unsigned char*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
3026
f_maybe_null(cdef->pack_flag) ? 1 : 0,
3027
cdef->pack_flag, cdef->sql_type, cdef->charset,
3029
cdef->interval, cdef->field_name);
3032
(*field)->init(table);
3033
record_length+= (*field)->pack_length();
3034
if (! ((*field)->flags & NOT_NULL_FLAG))
3037
if ((*field)->flags & BLOB_FLAG)
3038
share->blob_field[blob_count++]= (uint32_t) (field - table->field);
3042
*field= NULL; /* mark the end of the list */
3043
share->blob_field[blob_count]= 0; /* mark the end of the list */
3044
share->blob_fields= blob_count;
3046
null_pack_length= (null_count + 7)/8;
3047
share->reclength= record_length + null_pack_length;
3048
share->rec_buff_length= ALIGN_SIZE(share->reclength + 1);
3049
table->record[0]= (unsigned char*) session->alloc(share->rec_buff_length);
3050
if (!table->record[0])
3053
if (null_pack_length)
3055
table->null_flags= (unsigned char*) table->record[0];
3056
share->null_fields= null_count;
3057
share->null_bytes= null_pack_length;
3060
table->in_use= session; /* field->reset() may access table->in_use */
3062
/* Set up field pointers */
3063
unsigned char *null_pos= table->record[0];
3064
unsigned char *field_pos= null_pos + share->null_bytes;
3065
uint32_t null_bit= 1;
3067
for (field= table->field; *field; ++field)
3069
Field *cur_field= *field;
3070
if ((cur_field->flags & NOT_NULL_FLAG))
3071
cur_field->move_field(field_pos);
3074
cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
3076
if (null_bit == (1 << 8))
3084
field_pos+= cur_field->pack_length();
3089
for (field= table->field; *field; ++field)
3090
delete *field; /* just invokes field destructor */
3094
bool Table::open_tmp_table()
3097
if ((error=file->ha_open(this, s->table_name.str,O_RDWR,
3098
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
3100
file->print_error(error,MYF(0)); /* purecov: inspected */
3104
(void) file->extra(HA_EXTRA_QUICK); /* Faster */
3110
Create MyISAM temporary table
3113
create_myisam_tmp_table()
3114
keyinfo Description of the index (there is always one index)
3115
start_recinfo MyISAM's column descriptions
3116
recinfo INOUT End of MyISAM's column descriptions
3120
Create a MyISAM temporary table according to passed description. The is
3121
assumed to have one unique index or constraint.
3123
The passed array or MI_COLUMNDEF structures must have this form:
3125
1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
3126
when there are many nullable columns)
3128
3. One free MI_COLUMNDEF element (*recinfo points here)
3130
This function may use the free element to create hash column for unique
3138
bool Table::create_myisam_tmp_table(KEY *keyinfo,
3139
MI_COLUMNDEF *start_recinfo,
3140
MI_COLUMNDEF **recinfo,
3145
MI_UNIQUEDEF uniquedef;
3146
TableShare *share= s;
3149
{ // Get keys for ni_create
3150
bool using_unique_constraint= 0;
3151
HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&this->mem_root,
3152
sizeof(*seg) * keyinfo->key_parts);
3156
memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
3157
if (keyinfo->key_length >= file->max_key_length() ||
3158
keyinfo->key_parts > file->max_key_parts() ||
3161
/* Can't create a key; Make a unique constraint instead of a key */
3164
using_unique_constraint=1;
3165
memset(&uniquedef, 0, sizeof(uniquedef));
3166
uniquedef.keysegs=keyinfo->key_parts;
3168
uniquedef.null_are_equal=1;
3170
/* Create extra column for hash value */
3171
memset(*recinfo, 0, sizeof(**recinfo));
3172
(*recinfo)->type= FIELD_CHECK;
3173
(*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
3175
share->reclength+=MI_UNIQUE_HASH_LENGTH;
3179
/* Create an unique key */
3180
memset(&keydef, 0, sizeof(keydef));
3181
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
3182
keydef.keysegs= keyinfo->key_parts;
3185
for (uint32_t i= 0; i < keyinfo->key_parts ; i++,seg++)
3187
Field *key_field=keyinfo->key_part[i].field;
3189
seg->language= key_field->charset()->number;
3190
seg->length= keyinfo->key_part[i].length;
3191
seg->start= keyinfo->key_part[i].offset;
3192
if (key_field->flags & BLOB_FLAG)
3195
((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
3196
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
3197
seg->bit_start= (uint8_t)(key_field->pack_length()
3198
- share->blob_ptr_size);
3199
seg->flag= HA_BLOB_PART;
3200
seg->length= 0; // Whole blob in unique constraint
3204
seg->type= keyinfo->key_part[i].type;
3206
if (!(key_field->flags & NOT_NULL_FLAG))
3208
seg->null_bit= key_field->null_bit;
3209
seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) record[0]);
3211
We are using a GROUP BY on something that contains NULL
3212
In this case we have to tell MyISAM that two NULL should
3213
on INSERT be regarded at the same value
3215
if (!using_unique_constraint)
3216
keydef.flag|= HA_NULL_ARE_EQUAL;
3220
MI_CREATE_INFO create_info;
3221
memset(&create_info, 0, sizeof(create_info));
3223
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
3225
create_info.data_file_length= ~(uint64_t) 0;
3227
if ((error=mi_create(share->table_name.str, share->keys, &keydef,
3228
(uint32_t) (*recinfo-start_recinfo),
3230
share->uniques, &uniquedef,
3232
HA_CREATE_TMP_TABLE)))
3234
file->print_error(error,MYF(0)); /* purecov: inspected */
3238
status_var_increment(in_use->status_var.created_tmp_disk_tables);
3239
share->db_record_offset= 1;
3246
void Table::free_tmp_table(Session *session)
3248
MEM_ROOT own_root= mem_root;
3249
const char *save_proc_info;
3251
save_proc_info=session->get_proc_info();
3252
session->set_proc_info("removing tmp table");
3254
// Release latches since this can take a long time
3255
ha_release_temporary_latches(session);
3260
file->ha_drop_table(s->table_name.str);
3262
s->db_type()->deleteTable(session, s->table_name.str);
3267
for (Field **ptr= field ; *ptr ; ptr++)
3269
free_io_cache(this);
3271
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
3272
session->set_proc_info(save_proc_info);
3276
If a HEAP table gets full, create a MyISAM table and copy all rows
3280
bool create_myisam_from_heap(Session *session, Table *table,
3281
MI_COLUMNDEF *start_recinfo,
3282
MI_COLUMNDEF **recinfo,
3283
int error, bool ignore_last_dupp_key_error)
3287
const char *save_proc_info;
3290
if (table->s->db_type() != heap_engine ||
3291
error != HA_ERR_RECORD_FILE_FULL)
3293
table->file->print_error(error,MYF(0));
3297
// Release latches since this can take a long time
3298
ha_release_temporary_latches(session);
3302
new_table.s= &share;
3303
new_table.s->storage_engine= myisam_engine;
3304
if (!(new_table.file= get_new_handler(&share, &new_table.mem_root,
3305
new_table.s->db_type())))
3306
return true; // End of memory
3308
save_proc_info=session->get_proc_info();
3309
session->set_proc_info("converting HEAP to MyISAM");
3311
if (new_table.create_myisam_tmp_table(table->key_info, start_recinfo,
3312
recinfo, session->lex->select_lex.options |
3315
if (new_table.open_tmp_table())
3317
if (table->file->indexes_are_disabled())
3318
new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
3319
table->file->ha_index_or_rnd_end();
3320
table->file->ha_rnd_init(1);
3323
new_table.file->extra(HA_EXTRA_NO_ROWS);
3324
new_table.no_rows=1;
3327
/* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
3328
new_table.file->extra(HA_EXTRA_WRITE_CACHE);
3331
copy all old rows from heap table to MyISAM table
3332
This is the only code that uses record[1] to read/write but this
3333
is safe as this is a temporary MyISAM table without timestamp/autoincrement.
3335
while (!table->file->rnd_next(new_table.record[1]))
3337
write_err= new_table.file->ha_write_row(new_table.record[1]);
3341
/* copy row that filled HEAP table */
3342
if ((write_err=new_table.file->ha_write_row(table->record[0])))
3344
if (new_table.file->is_fatal_error(write_err, HA_CHECK_DUP) ||
3345
!ignore_last_dupp_key_error)
3349
/* remove heap table and change to use myisam table */
3350
(void) table->file->ha_rnd_end();
3351
(void) table->file->close(); // This deletes the table !
3354
new_table.s= table->s; // Keep old share
3358
table->file->change_table_ptr(table, table->s);
3359
table->use_all_columns();
3362
const char *new_proc_info=
3363
(!strcmp(save_proc_info,"Copying to tmp table") ?
3364
"Copying to tmp table on disk" : save_proc_info);
3365
session->set_proc_info(new_proc_info);
3370
table->file->print_error(write_err, MYF(0));
3371
(void) table->file->ha_rnd_end();
3372
(void) new_table.file->close();
3374
new_table.s->db_type()->deleteTable(session, new_table.s->table_name.str);
3376
delete new_table.file;
3377
session->set_proc_info(save_proc_info);
3378
table->mem_root= new_table.mem_root;
3382
my_bitmap_map *Table::use_all_columns(MY_BITMAP *bitmap)
3384
my_bitmap_map *old= bitmap->bitmap;
3385
bitmap->bitmap= s->all_set.bitmap;
1421
void Table::restore_column_map(const boost::dynamic_bitset<>& old)
3389
void Table::restore_column_map(my_bitmap_map *old)
1423
for (boost::dynamic_bitset<>::size_type i= 0; i < old.size(); i++)
3391
read_set->bitmap= old;
1436
3394
uint32_t Table::find_shortest_key(const key_map *usable_keys)