12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
17
/* Some general useful functions */
19
#include <drizzled/server_includes.h>
28
20
#include <drizzled/error.h>
29
21
#include <drizzled/gettext.h>
31
#include "drizzled/plugin/transactional_storage_engine.h"
32
#include "drizzled/plugin/authorization.h"
23
#include <drizzled/tmp_table.h>
24
#include <drizzled/sj_tmp_table.h>
33
25
#include <drizzled/nested_join.h>
26
#include <drizzled/data_home.h>
34
27
#include <drizzled/sql_parse.h>
35
28
#include <drizzled/item/sum.h>
29
#include <drizzled/virtual_column_info.h>
36
30
#include <drizzled/table_list.h>
37
31
#include <drizzled/session.h>
38
32
#include <drizzled/sql_base.h>
39
#include <drizzled/sql_select.h>
40
33
#include <drizzled/field/blob.h>
41
34
#include <drizzled/field/varstring.h>
42
35
#include <drizzled/field/double.h>
43
38
#include <drizzled/unireg.h>
44
#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
#include <drizzled/item/string.h>
52
#include <drizzled/item/int.h>
53
#include <drizzled/item/decimal.h>
54
#include <drizzled/item/float.h>
55
#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"
39
#include <drizzled/serialize/table.pb.h>
64
41
using namespace std;
69
extern plugin::StorageEngine *heap_engine;
70
extern plugin::StorageEngine *myisam_engine;
72
/* Functions defined in this cursor */
43
/* Keyword for parsing virtual column functions */
44
LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
46
/* Functions defined in this file */
48
void open_table_error(TABLE_SHARE *share, int error, int db_errno,
49
myf errortype, int errarg);
50
static int open_binary_frm(Session *session, TABLE_SHARE *share,
51
unsigned char *head, File file);
52
static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
53
uint32_t types, char **names);
74
55
/*************************************************************************/
76
// @note this should all be the destructor
77
int Table::delete_table(bool free_share)
57
/* Get column name from column hash */
59
static unsigned char *get_field_name(Field **buff, size_t *length, bool)
61
*length= (uint32_t) strlen((*buff)->field_name);
62
return (unsigned char*) (*buff)->field_name;
67
Returns pointer to '.frm' extension of the file name.
74
Checks file name part starting with the rightmost '.' character,
75
and returns it if it is equal to '.frm'.
78
It is a good idea to get rid of this function modifying the code
79
to garantee that the functions presently calling fn_rext() always
80
get arguments in the same format: either with '.frm' or without '.frm'.
83
Pointer to the '.frm' extension. If there is no extension,
84
or extension is not '.frm', pointer at the end of file name.
87
char *fn_rext(char *name)
89
char *res= strrchr(name, '.');
90
if (res && !strcmp(res, reg_ext))
92
return name + strlen(name);
95
TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name)
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 TABLE_SHARE 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
TABLE_SHARE *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, "", 0);
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;
158
This constant is used to mark that no table map version has been
159
assigned. No arithmetic is done on the value: it will be
160
overwritten with a value taken from DRIZZLE_BIN_LOG.
162
share->table_map_version= UINT64_MAX;
165
Since alloc_table_share() can be called without any locking (for
166
example, ha_create_table... functions), we do not assign a table
167
map id here. Instead we assign a value that is not used
168
elsewhere, and then assign a table map id inside open_table()
169
under the protection of the LOCK_open mutex.
171
share->table_map_id= UINT32_MAX;
172
share->cached_row_logging_check= -1;
174
memcpy(&share->mem_root, &mem_root, sizeof(mem_root));
175
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
176
pthread_cond_init(&share->cond, NULL);
183
Initialize share for temporary tables
186
init_tmp_table_share()
187
session thread handle
189
key Table_cache_key, as generated from create_table_def_key.
190
must start with db name.
191
key_length Length of key
192
table_name Table name
193
path Path to file (possible in lower case) without .frm
196
This is different from alloc_table_share() because temporary tables
197
don't have to be shared between threads or put into the table def
198
cache, so we can do some things notable simpler and faster
200
If table is not put in session->temporary_tables (happens only when
201
one uses OPEN TEMPORARY) then one can specify 'db' as key and
202
use key_length= 0 as neither table_cache_key or key_length will be used).
205
void init_tmp_table_share(Session *session, TABLE_SHARE *share, const char *key,
206
uint32_t key_length, const char *table_name,
210
memset(share, 0, sizeof(*share));
211
init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
212
share->table_category= TABLE_CATEGORY_TEMPORARY;
213
share->tmp_table= INTERNAL_TMP_TABLE;
214
share->db.str= (char*) key;
215
share->db.length= strlen(key);
216
share->table_cache_key.str= (char*) key;
217
share->table_cache_key.length= key_length;
218
share->table_name.str= (char*) table_name;
219
share->table_name.length= strlen(table_name);
220
share->path.str= (char*) path;
221
share->normalized_path.str= (char*) path;
222
share->path.length= share->normalized_path.length= strlen(path);
225
Temporary tables are not replicated, but we set up these fields
226
anyway to be able to catch errors.
228
share->table_map_version= ~(uint64_t)0;
229
share->cached_row_logging_check= -1;
232
table_map_id is also used for MERGE tables to suppress repeated
233
compatibility checks.
235
share->table_map_id= (ulong) session->query_id;
242
Free table share and memory used by it
249
share->mutex must be locked when we come here if it's not a temp table
252
void free_table_share(TABLE_SHARE *share)
255
assert(share->ref_count == 0);
258
If someone is waiting for this to be deleted, inform it about this.
259
Don't do a delete until we know that no one is refering to this anymore.
261
if (share->tmp_table == NO_TMP_TABLE)
263
/* share->mutex is locked in release_table_share() */
264
while (share->waiting_on_cond)
266
pthread_cond_broadcast(&share->cond);
267
pthread_cond_wait(&share->cond, &share->mutex);
269
/* No thread refers to this anymore */
270
pthread_mutex_unlock(&share->mutex);
271
pthread_mutex_destroy(&share->mutex);
272
pthread_cond_destroy(&share->cond);
274
hash_free(&share->name_hash);
276
plugin_unlock(NULL, share->db_plugin);
277
share->db_plugin= NULL;
279
/* We must copy mem_root from share because share is allocated through it */
280
memcpy(&mem_root, &share->mem_root, sizeof(mem_root));
281
free_root(&mem_root, MYF(0)); // Free's share
285
enum_field_types proto_field_type_to_drizzle_type(uint32_t proto_field_type)
287
enum_field_types field_type;
289
switch(proto_field_type)
291
case drizzle::Table::Field::TINYINT:
292
field_type= DRIZZLE_TYPE_TINY;
294
case drizzle::Table::Field::INTEGER:
295
field_type= DRIZZLE_TYPE_LONG;
297
case drizzle::Table::Field::DOUBLE:
298
field_type= DRIZZLE_TYPE_DOUBLE;
300
case drizzle::Table::Field::TIMESTAMP:
301
field_type= DRIZZLE_TYPE_TIMESTAMP;
303
case drizzle::Table::Field::BIGINT:
304
field_type= DRIZZLE_TYPE_LONGLONG;
306
case drizzle::Table::Field::TIME:
307
field_type= DRIZZLE_TYPE_TIME;
309
case drizzle::Table::Field::DATETIME:
310
field_type= DRIZZLE_TYPE_DATETIME;
312
case drizzle::Table::Field::DATE:
313
field_type= DRIZZLE_TYPE_DATE;
315
case drizzle::Table::Field::VARCHAR:
316
field_type= DRIZZLE_TYPE_VARCHAR;
318
case drizzle::Table::Field::DECIMAL:
319
field_type= DRIZZLE_TYPE_NEWDECIMAL;
321
case drizzle::Table::Field::ENUM:
322
field_type= DRIZZLE_TYPE_ENUM;
324
case drizzle::Table::Field::BLOB:
325
field_type= DRIZZLE_TYPE_BLOB;
327
case drizzle::Table::Field::VIRTUAL:
328
field_type= DRIZZLE_TYPE_VIRTUAL;
337
int parse_table_proto(Session *session, drizzle::Table &table, TABLE_SHARE *share)
340
LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
341
strlen(table.engine().name().c_str()) };
342
share->db_plugin= ha_resolve_by_name(session, &engine_name);
345
// share->db_create_options FAIL
346
// share->db_options_in_use FAIL
347
share->mysql_version= DRIZZLE_VERSION_ID; // TODO: remove
349
drizzle::Table::TableOptions table_options;
351
if(table.has_options())
352
table_options= table.options();
354
share->avg_row_length= table_options.has_avg_row_length() ?
355
table_options.avg_row_length() : 0;
357
share->page_checksum= table_options.has_page_checksum() ?
358
(table_options.page_checksum()?HA_CHOICE_YES:HA_CHOICE_NO)
361
share->row_type= table_options.has_row_type() ?
362
(enum row_type) table_options.row_type() : ROW_TYPE_DEFAULT;
364
share->block_size= table_options.has_block_size() ?
365
table_options.block_size() : 0;
367
share->table_charset= get_charset(table_options.has_collation_id()?
368
table_options.collation_id() : 0);
370
if (!share->table_charset)
372
/* unknown charset in head[38] or pre-3.23 frm */
373
if (use_mb(default_charset_info))
375
/* Warn that we may be changing the size of character columns */
376
errmsg_printf(ERRMSG_LVL_WARN,
377
_("'%s' had no or invalid character set, "
378
"and default character set is multi-byte, "
379
"so character column sizes may have changed"),
382
share->table_charset= default_charset_info;
385
share->db_record_offset= 1;
387
share->blob_ptr_size= portable_sizeof_char_ptr; // more bonghits.
389
share->db_low_byte_first= true;
391
share->max_rows= table_options.has_max_rows() ?
392
table_options.max_rows() : 0;
394
share->min_rows= table_options.has_min_rows() ?
395
table_options.min_rows() : 0;
397
share->keys= table.indexes_size();
400
for(int indx= 0; indx < table.indexes_size(); indx++)
401
share->key_parts+= table.indexes(indx).index_part_size();
403
share->key_info= (KEY*) alloc_root(&share->mem_root,
404
table.indexes_size() * sizeof(KEY)
405
+share->key_parts*sizeof(KEY_PART_INFO));
407
KEY_PART_INFO *key_part;
409
key_part= reinterpret_cast<KEY_PART_INFO*>
410
(share->key_info+table.indexes_size());
413
ulong *rec_per_key= (ulong*) alloc_root(&share->mem_root,
414
sizeof(ulong*)*share->key_parts);
416
share->keynames.count= table.indexes_size();
417
share->keynames.name= NULL;
418
share->keynames.type_names= (const char**)
419
alloc_root(&share->mem_root, sizeof(char*) * (table.indexes_size()+1));
421
share->keynames.type_lengths= (unsigned int*)
422
alloc_root(&share->mem_root,
423
sizeof(unsigned int) * (table.indexes_size()+1));
425
share->keynames.type_names[share->keynames.count]= NULL;
426
share->keynames.type_lengths[share->keynames.count]= 0;
428
KEY* keyinfo= share->key_info;
429
for (int keynr=0; keynr < table.indexes_size(); keynr++, keyinfo++)
431
drizzle::Table::Index indx= table.indexes(keynr);
437
keyinfo->flags|= HA_NOSAME;
439
if(indx.has_options())
441
drizzle::Table::Index::IndexOptions indx_options= indx.options();
442
if(indx_options.pack_key())
443
keyinfo->flags|= HA_PACK_KEY;
445
if(indx_options.var_length_key())
446
keyinfo->flags|= HA_VAR_LENGTH_PART;
448
if(indx_options.null_part_key())
449
keyinfo->flags|= HA_NULL_PART_KEY;
451
if(indx_options.binary_pack_key())
452
keyinfo->flags|= HA_BINARY_PACK_KEY;
454
if(indx_options.has_partial_segments())
455
keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
457
if(indx_options.auto_generated_key())
458
keyinfo->flags|= HA_GENERATED_KEY;
460
if(indx_options.has_key_block_size())
462
keyinfo->flags|= HA_USES_BLOCK_SIZE;
463
keyinfo->block_size= indx_options.key_block_size();
467
keyinfo->block_size= 0;
474
case drizzle::Table::Index::UNKNOWN_INDEX:
475
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
477
case drizzle::Table::Index::BTREE:
478
keyinfo->algorithm= HA_KEY_ALG_BTREE;
480
case drizzle::Table::Index::RTREE:
481
keyinfo->algorithm= HA_KEY_ALG_RTREE;
483
case drizzle::Table::Index::HASH:
484
keyinfo->algorithm= HA_KEY_ALG_HASH;
486
case drizzle::Table::Index::FULLTEXT:
487
keyinfo->algorithm= HA_KEY_ALG_FULLTEXT;
490
/* TODO: suitable warning ? */
491
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
495
keyinfo->key_length= indx.key_length();
497
keyinfo->key_parts= indx.index_part_size();
499
keyinfo->key_part= key_part;
500
keyinfo->rec_per_key= rec_per_key;
502
for(unsigned int partnr= 0;
503
partnr < keyinfo->key_parts;
504
partnr++, key_part++)
506
drizzle::Table::Index::IndexPart part;
507
part= indx.index_part(partnr);
511
key_part->field= NULL;
512
key_part->fieldnr= part.fieldnr();
513
key_part->null_bit= 0;
514
/* key_part->offset= ASS ASS ASS. Set later in the frm code */
515
/* key_part->null_offset is only set if null_bit (see later) */
516
/* key_part->key_type= */ /* I *THINK* this may be okay.... */
517
/* key_part->type ???? */
518
key_part->key_part_flag= 0;
519
if(part.has_in_reverse_order())
520
key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
522
key_part->length= part.compare_length();
524
key_part->store_length= key_part->length;
527
if(!indx.has_comment())
529
keyinfo->comment.length= 0;
530
keyinfo->comment.str= NULL;
534
keyinfo->flags|= HA_USES_COMMENT;
535
keyinfo->comment.length= indx.comment().length();
536
keyinfo->comment.str= strmake_root(&share->mem_root,
537
indx.comment().c_str(),
538
keyinfo->comment.length);
541
keyinfo->name= strmake_root(&share->mem_root,
543
indx.name().length());
545
share->keynames.type_names[keynr]= keyinfo->name;
546
share->keynames.type_lengths[keynr]= indx.name().length();
549
share->keys_for_keyread.init(0);
550
share->keys_in_use.init(share->keys);
552
if(table_options.has_connect_string())
554
size_t len= table_options.connect_string().length();
555
const char* str= table_options.connect_string().c_str();
557
share->connect_string.length= len;
558
share->connect_string.str= strmake_root(&share->mem_root, str, len);
561
if(table_options.has_comment())
563
size_t len= table_options.comment().length();
564
const char* str= table_options.comment().c_str();
566
share->comment.length= len;
567
share->comment.str= strmake_root(&share->mem_root, str, len);
570
share->key_block_size= table_options.has_key_block_size() ?
571
table_options.key_block_size() : 0;
573
share->fields= table.field_size();
575
share->stored_fields= share->fields;
577
/* share->field= (Field**) alloc_root(&share->mem_root,
578
(share->fields * sizeof(Field*)));
580
uint32_t null_fields= 0;
583
uint32_t *field_offsets= (uint32_t*)malloc(share->fields * sizeof(uint32_t));
584
uint32_t *field_pack_length=(uint32_t*)malloc(share->fields*sizeof(uint32_t));
586
assert(field_offsets && field_pack_length); // TODO: fixme
588
for(unsigned int fieldnr=0; fieldnr < share->fields; fieldnr++)
590
drizzle::Table::Field pfield= table.field(fieldnr);
591
if(pfield.has_constraints() && pfield.constraints().is_nullable())
594
field_offsets[fieldnr]= share->reclength;
596
enum_field_types drizzle_field_type=
597
proto_field_type_to_drizzle_type(pfield.type());
599
if(drizzle_field_type==DRIZZLE_TYPE_VIRTUAL)
601
drizzle::Table::Field::VirtualFieldOptions field_options=
602
pfield.virtual_options();
604
drizzle_field_type=proto_field_type_to_drizzle_type(field_options.type());
607
/* the below switch is very similar to
608
Create_field::create_length_to_internal_length in field.cc
609
(which should one day be replace by just this code)
611
switch(drizzle_field_type)
613
case DRIZZLE_TYPE_BLOB:
614
case DRIZZLE_TYPE_VARCHAR:
616
drizzle::Table::Field::StringFieldOptions field_options=
617
pfield.string_options();
619
const CHARSET_INFO *cs= get_charset(field_options.has_collation_id()?
620
field_options.collation_id() : 0);
623
cs= default_charset_info;
625
field_pack_length[fieldnr]=
626
calc_pack_length(drizzle_field_type,
627
field_options.length() * cs->mbmaxlen);
631
case DRIZZLE_TYPE_ENUM:
633
drizzle::Table::Field::SetFieldOptions field_options=
634
pfield.set_options();
636
field_pack_length[fieldnr]=
637
get_enum_pack_length(field_options.field_value_size());
640
case DRIZZLE_TYPE_NEWDECIMAL:
642
drizzle::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
644
field_pack_length[fieldnr]=
645
my_decimal_get_binary_size(fo.precision(), fo.scale());
649
/* Zero is okay here as length is fixed for other types. */
650
field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
653
share->reclength+= field_pack_length[fieldnr];
656
ulong null_bits= null_fields;
657
if(!table_options.pack_record())
659
ulong data_offset= (null_bits + 7)/8;
661
share->reclength+= data_offset;
663
ulong rec_buff_length;
665
rec_buff_length= ALIGN_SIZE(share->reclength + 1);
666
share->rec_buff_length= rec_buff_length;
668
unsigned char* record= NULL;
670
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
674
share->default_values= record;
676
for(unsigned int fieldnr=0; fieldnr < share->fields; fieldnr++)
678
drizzle::Table::Field pfield= table.field(fieldnr);
680
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
682
switch(pfield.format())
684
case drizzle::Table::Field::DefaultFormat:
685
column_format= COLUMN_FORMAT_TYPE_DEFAULT;
687
case drizzle::Table::Field::FixedFormat:
688
column_format= COLUMN_FORMAT_TYPE_FIXED;
690
case drizzle::Table::Field::DynamicFormat:
691
column_format= COLUMN_FORMAT_TYPE_DYNAMIC;
697
Field::utype unireg_type= Field::NONE;
699
if(pfield.has_numeric_options()
700
&& pfield.numeric_options().is_autoincrement())
702
unireg_type= Field::NEXT_NUMBER;
705
if(pfield.has_options()
706
&& pfield.options().has_default_value()
707
&& pfield.options().default_value().compare("NOW()")==0)
709
if(pfield.options().has_update_value()
710
&& pfield.options().update_value().compare("NOW()")==0)
712
unireg_type= Field::TIMESTAMP_DNUN_FIELD;
714
else if (!pfield.options().has_update_value())
716
unireg_type= Field::TIMESTAMP_DN_FIELD;
719
abort(); // Invalid update value.
721
else if (pfield.has_options()
722
&& pfield.options().has_update_value()
723
&& pfield.options().update_value().compare("NOW()")==0)
725
unireg_type= Field::TIMESTAMP_UN_FIELD;
729
if(!pfield.has_comment())
731
comment.str= (char*)"";
736
size_t len= pfield.comment().length();
737
const char* str= pfield.comment().c_str();
739
comment.str= strmake_root(&share->mem_root, str, len);
743
enum_field_types field_type;
744
virtual_column_info *vcol_info= NULL;
745
bool field_is_stored= true;
748
field_type= proto_field_type_to_drizzle_type(pfield.type());
750
if(field_type==DRIZZLE_TYPE_VIRTUAL)
752
drizzle::Table::Field::VirtualFieldOptions field_options=
753
pfield.virtual_options();
755
vcol_info= new virtual_column_info();
756
field_type= proto_field_type_to_drizzle_type(field_options.type());
757
field_is_stored= field_options.physically_stored();
759
size_t len= field_options.expression().length();
760
const char* str= field_options.expression().c_str();
762
vcol_info->expr_str.str= strmake_root(&share->mem_root, str, len);
763
vcol_info->expr_str.length= len;
768
// TODO: charset (well... collation)
770
/* share->field[fieldnr]= make_field(share, record+recordpos,
772
null_pos, null_bit_pos,
776
(Field::utype) MTYP_TYPENR(unireg_type),
778
share->intervals+interval_nr-1 :
780
share->fieldnames.type_names[i]);
785
free(field_pack_length);
791
Read table definition from a binary / text based .frm file
795
session Thread handler
796
share Fill this with table definition
797
db_flags Bit mask of the following flags: OPEN_VIEW
800
This function is called when the table definition is not cached in
802
The data is returned in 'share', which is alloced by
803
alloc_table_share().. The code assumes that share is initialized.
807
1 Error (see open_table_error)
808
2 Error (see open_table_error)
809
3 Wrong data in .frm file
810
4 Error (see open_table_error)
811
5 Error (see open_table_error: charset unavailable)
812
6 Unknown .frm version
815
int open_table_def(Session *session, TABLE_SHARE *share, uint32_t)
817
int error, table_type;
820
unsigned char head[64], *disk_buff;
823
MEM_ROOT **root_ptr, *old_root;
829
path.reserve(FN_REFLEN);
830
path.append(share->normalized_path.str);
831
string proto_path= path;
833
path.append(reg_ext);
835
proto_path.append(".dfe");
837
drizzle::Table table;
839
if((error= drizzle_read_table_proto(proto_path.c_str(), &table)))
848
if(!table.IsInitialized())
856
parse_table_proto(session, table, share);
858
/* end of proto code... now to get some scraps from FRM */
860
if ((file= open(path.c_str(), O_RDONLY)) < 0)
863
We don't try to open 5.0 unencoded name, if
864
- non-encoded name contains '@' signs,
865
because '@' can be misinterpreted.
866
It is not clear if '@' is escape character in 5.1,
867
or a normal character in 5.0.
869
- non-encoded db or table name contain "#mysql50#" prefix.
870
This kind of tables must have been opened only by the
873
if (strchr(share->table_name.str, '@') ||
874
!strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX,
875
MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
876
!strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX,
877
MYSQL50_TABLE_NAME_PREFIX_LENGTH))
880
/* Try unencoded 5.0 name */
882
char unpacked_path[FN_REFLEN];
884
path.append(drizzle_data_home);
886
path.append(share->db.str);
888
path.append(share->table_name.str);
889
path.append(reg_ext);
890
length= unpack_filename(unpacked_path, path.c_str()) - reg_ext_length;
892
The following is a safety test and should never fail
893
as the old file name should never be longer than the new one.
895
assert(length <= share->normalized_path.length);
897
If the old and the new names have the same length,
898
then table name does not have tricky characters,
899
so no need to check the old file name.
901
if (length == share->normalized_path.length ||
902
((file= open(unpacked_path, O_RDONLY)) < 0))
905
/* Unencoded 5.0 table name found */
906
unpacked_path[length]= '\0'; // Remove .frm extension
907
strcpy(share->normalized_path.str, unpacked_path);
908
share->normalized_path.length= length;
912
if (my_read(file, head, 64, MYF(MY_NABP)))
915
if (head[0] == (unsigned char) 254 && head[1] == 1)
917
if (head[2] == FRM_VER || head[2] == FRM_VER+1 ||
918
(head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4))
924
error= 6; // Unkown .frm version
931
/* No handling of text based files yet */
934
root_ptr= current_mem_root_ptr();
936
*root_ptr= &share->mem_root;
937
error= open_binary_frm(session, share, head, file);
944
share->table_category= get_table_category(& share->db, & share->table_name);
947
session->status_var.opened_shares++;
950
my_close(file, MYF(MY_WME));
953
if (error && !error_given)
956
open_table_error(share, error, (share->open_errno= my_errno), 0);
964
Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
967
static int open_binary_frm(Session *session, TABLE_SHARE *share, unsigned char *head,
970
int error, errarg= 0;
971
uint32_t new_frm_ver, field_pack_length, new_field_pack_flag;
972
uint32_t interval_count, interval_parts, read_length, int_length;
973
uint32_t db_create_options, keys, key_parts, n_length;
974
uint32_t key_info_length, com_length, null_bit_pos=0;
975
uint32_t vcol_screen_length;
978
unsigned char forminfo[288];
979
char *names, *comment_pos, *vcol_screen_pos;
980
unsigned char *record;
981
unsigned char *disk_buff, *strpos, *null_flags=NULL, *null_pos=NULL;
982
ulong pos, record_offset, rec_buff_length;
983
handler *handler_file= 0;
985
KEY_PART_INFO *key_part;
986
Field **field_ptr, *reg_field;
987
const char **interval_array;
988
my_bitmap_map *bitmaps;
989
unsigned char *buff= 0;
990
unsigned char *field_extra_info= 0;
992
new_field_pack_flag= head[27];
993
new_frm_ver= (head[2] - FRM_VER);
994
assert(new_frm_ver >= 2); /* If this fails, we're on old FRM */
995
field_pack_length= 17;
999
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
1000
goto err; /* purecov: inspected */
1001
lseek(file,pos,SEEK_SET);
1002
if (my_read(file,forminfo,288,MYF(MY_NABP)))
1005
share->db_create_options= db_create_options= uint2korr(head+30);
1006
share->db_options_in_use= share->db_create_options;
1010
/* Read keyinformation */
1011
key_info_length= (uint32_t) uint2korr(head+28);
1012
lseek(file,(ulong) uint2korr(head+6),SEEK_SET);
1013
if (read_string(file,(unsigned char**) &disk_buff,key_info_length))
1014
goto err; /* purecov: inspected */
1015
if (disk_buff[0] & 0x80)
1017
/*share->keys=*/ keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
1018
/*share->key_parts=*/ key_parts= uint2korr(disk_buff+2);
1022
/*share->keys= */keys= disk_buff[0];
1023
/*share->key_parts=*/ key_parts= disk_buff[1];
1026
/* the magic uint2korr(disk_buff+4) is the key names size */
1028
keyinfo= share->key_info;
1029
key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo+keys);
1032
for (i=0 ; i < keys ; i++, keyinfo++)
1034
if (new_frm_ver >= 3)
1039
for (j=keyinfo->key_parts ; j-- ; key_part++)
1041
key_part->offset= (uint32_t) uint2korr(strpos+2)-1;
1042
key_part->key_type= (uint32_t) uint2korr(strpos+5);
1043
if (new_frm_ver >= 1)
1049
abort(); // Old FRM version, we abort as we should never see it.
1054
// keynames=(char*) key_part;
1055
// strpos+= (strcpy(keynames, (char*)strpos)+strlen((char*)strpos)-keynames)+1;
1057
//reading index comments
1058
for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
1060
if (keyinfo->flags & HA_USES_COMMENT)
1062
// keyinfo->comment.length= uint2korr(strpos);
1063
// keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos+2,
1064
// keyinfo->comment.length);
1065
strpos+= 2 + uint2korr(strpos);//keyinfo->comment.length;
1067
// assert(test(keyinfo->flags & HA_USES_COMMENT) ==
1068
// (keyinfo->comment.length > 0));
1071
assert(share->reclength == uint2korr((head+16)));
1072
share->stored_rec_length= share->reclength;
1074
record_offset= (ulong) (uint2korr(head+6)+
1075
((uint2korr(head+14) == 0xffff ?
1076
uint4korr(head+47) : uint2korr(head+14))));
1078
if ((n_length= uint4korr(head+55)))
1080
/* Read extra data segment */
1081
unsigned char *next_chunk, *buff_end;
1082
if (!(next_chunk= buff= (unsigned char*) malloc(n_length)))
1084
if (pread(file, buff, n_length, record_offset + share->reclength) == 0)
1089
uint32_t connect_str_length= uint2korr(buff);
1090
next_chunk+= connect_str_length + 2;
1092
buff_end= buff + n_length;
1093
if (next_chunk + 2 < buff_end)
1095
uint32_t str_db_type_length= uint2korr(next_chunk);
1096
next_chunk+= str_db_type_length + 2;
1098
if (share->mysql_version >= 50110)
1100
/* New auto_partitioned indicator introduced in 5.1.11 */
1103
if (forminfo[46] == (unsigned char)255)
1105
//reading long table comment
1106
if (next_chunk + 2 > buff_end)
1111
uint32_t comment_str_length= uint2korr(next_chunk);
1112
next_chunk+= 2 + comment_str_length;
1114
assert(next_chunk <= buff_end);
1115
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM_CGE)
1118
New frm format in mysql_version 5.2.5 (originally in
1119
mysql-5.1.22-ndb-6.2.5)
1120
New column properties added:
1121
COLUMN_FORMAT DYNAMIC|FIXED and STORAGE DISK|MEMORY
1122
TABLESPACE name is now stored in frm
1124
if (next_chunk >= buff_end)
1126
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM)
1133
const uint32_t format_section_header_size= 8;
1134
uint32_t format_section_len= uint2korr(next_chunk+0);
1135
uint32_t flags= uint4korr(next_chunk+2);
1139
const char *tablespace= (const char*)next_chunk + format_section_header_size;
1140
uint32_t tablespace_len= strlen(tablespace);
1142
field_extra_info= next_chunk + format_section_header_size + tablespace_len + 1;
1143
next_chunk+= format_section_len;
1146
assert (next_chunk <= buff_end);
1147
if (next_chunk > buff_end)
1154
/* head+59 was extra_rec_buf_length */
1155
rec_buff_length= ALIGN_SIZE(share->reclength + 1);
1156
share->rec_buff_length= rec_buff_length;
1157
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
1159
goto err; /* purecov: inspected */
1160
share->default_values= record;
1161
if (pread(file, record, (size_t) share->reclength, record_offset) == 0)
1162
goto err; /* purecov: inspected */
1164
lseek(file,pos+288,SEEK_SET);
1166
// share->fields= uint2korr(forminfo+258);
1167
pos= uint2korr(forminfo+260); /* Length of all screens */
1168
n_length= uint2korr(forminfo+268);
1169
interval_count= uint2korr(forminfo+270);
1170
interval_parts= uint2korr(forminfo+272);
1171
int_length= uint2korr(forminfo+274);
1172
share->null_fields= uint2korr(forminfo+282);
1173
com_length= uint2korr(forminfo+284);
1174
vcol_screen_length= uint2korr(forminfo+286);
1175
// share->vfields= 0;
1176
// share->stored_fields= share->fields;
1179
/* WTF is with the share->fields+1 here... */
1180
if (!(field_ptr = (Field **)
1181
alloc_root(&share->mem_root,
1182
(uint32_t) ((share->fields+1)*sizeof(Field*)+
1183
interval_count*sizeof(TYPELIB)+
1184
(share->fields+interval_parts+
1185
keys+3)*sizeof(char *)+
1186
(n_length+int_length+
1187
vcol_screen_length)))))
1188
goto err; /* purecov: inspected */
1190
share->field= field_ptr;
1191
read_length=(uint32_t) (share->fields * field_pack_length +
1192
pos+ (uint32_t) (n_length+int_length+com_length+
1193
vcol_screen_length));
1194
if (read_string(file,(unsigned char**) &disk_buff,read_length))
1195
goto err; /* purecov: inspected */
1196
strpos= disk_buff+pos;
1198
share->intervals= (TYPELIB*) (field_ptr+share->fields+1);
1199
interval_array= (const char **) (share->intervals+interval_count);
1200
names= (char*) (interval_array+share->fields+interval_parts+keys+3);
1201
if (!interval_count)
1202
share->intervals= 0; // For better debugging
1203
memcpy(names, strpos+(share->fields*field_pack_length),
1204
(uint32_t) (n_length+int_length));
1205
comment_pos= (char *)(disk_buff+read_length-com_length-vcol_screen_length);
1206
vcol_screen_pos= names+(n_length+int_length);
1207
memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length,
1208
vcol_screen_length);
1210
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
1211
if (share->fieldnames.count != share->fields)
1213
fix_type_pointers(&interval_array, share->intervals, interval_count,
1217
/* Set ENUM and SET lengths */
1219
for (interval= share->intervals;
1220
interval < share->intervals + interval_count;
1223
uint32_t count= (uint32_t) (interval->count + 1) * sizeof(uint32_t);
1224
if (!(interval->type_lengths= (uint32_t *) alloc_root(&share->mem_root,
1227
for (count= 0; count < interval->count; count++)
1229
char *val= (char*) interval->type_names[count];
1230
interval->type_lengths[count]= strlen(val);
1232
interval->type_lengths[count]= 0;
1237
fix_type_pointers(&interval_array, &share->keynames, 1, &keynames);*/
1239
/* Allocate handler */
1240
if (!(handler_file= get_new_handler(share, session->mem_root,
1244
record= share->default_values-1; /* Fieldstart = 1 */
1246
null_flags= null_pos= (unsigned char*) record+1;
1247
null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
1249
null_bytes below is only correct under the condition that
1250
there are no bit fields. Correct values is set below after the
1251
table struct is initialized
1253
share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8;
1255
use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
1257
use_hash= !hash_init(&share->name_hash,
1258
system_charset_info,
1260
(hash_get_key) get_field_name,0,0);
1262
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
1264
uint32_t pack_flag, interval_nr, unireg_type, recpos, field_length;
1265
uint32_t vcol_info_length=0;
1266
enum_field_types field_type;
1267
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
1268
const CHARSET_INFO *charset= NULL;
1270
virtual_column_info *vcol_info= NULL;
1271
bool fld_is_stored= true;
1273
if (field_extra_info)
1275
char tmp= field_extra_info[i];
1276
column_format= (enum column_format_type)
1277
((tmp >> COLUMN_FORMAT_SHIFT) & COLUMN_FORMAT_MASK);
1279
if (new_frm_ver >= 3)
1281
/* new frm file in 4.1 */
1282
field_length= uint2korr(strpos+3);
1283
recpos= uint3korr(strpos+5);
1284
pack_flag= uint2korr(strpos+8);
1285
unireg_type= (uint32_t) strpos[10];
1286
interval_nr= (uint32_t) strpos[12];
1287
uint32_t comment_length=uint2korr(strpos+15);
1288
field_type=(enum_field_types) (uint32_t) strpos[13];
1292
charset= &my_charset_bin;
1293
else if (!(charset=get_charset((uint32_t) strpos[14])))
1295
error= 5; // Unknown or unavailable charset
1296
errarg= (int) strpos[14];
1300
if (field_type == DRIZZLE_TYPE_VIRTUAL)
1302
assert(interval_nr); // Expect non-null expression
1304
The interval_id byte in the .frm file stores the length of the
1305
expression statement for a virtual column.
1307
vcol_info_length= interval_nr;
1310
if (!comment_length)
1312
comment.str= (char*) "";
1317
comment.str= strmake_root(&share->mem_root, comment_pos, comment_length);
1318
comment.length= comment_length;
1319
comment_pos+= comment_length;
1321
if (vcol_info_length)
1324
Get virtual column data stored in the .frm file as follows:
1325
byte 1 = 1 (always 1 to allow for future extensions)
1327
byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
1328
byte 4-... = virtual column expression (text data)
1330
vcol_info= new virtual_column_info();
1331
if ((uint32_t)vcol_screen_pos[0] != 1)
1336
field_type= (enum_field_types) (unsigned char) vcol_screen_pos[1];
1337
fld_is_stored= (bool) (uint32_t) vcol_screen_pos[2];
1338
vcol_info->expr_str.str= (char *)memdup_root(&share->mem_root,
1340
(uint32_t)FRM_VCOL_HEADER_SIZE,
1342
(uint32_t)FRM_VCOL_HEADER_SIZE);
1343
vcol_info->expr_str.length= vcol_info_length-(uint32_t)FRM_VCOL_HEADER_SIZE;
1344
vcol_screen_pos+= vcol_info_length;
1350
assert(false); /* Old (pre-4.1) FRM file. This is Drizzle. */
1353
if (interval_nr && charset->mbminlen > 1)
1355
/* Unescape UCS2 intervals from HEX notation */
1356
TYPELIB *interval= share->intervals + interval_nr - 1;
1357
unhex_type2(interval);
1360
*field_ptr= reg_field=
1361
make_field(share, record+recpos,
1362
(uint32_t) field_length,
1363
null_pos, null_bit_pos,
1367
(Field::utype) MTYP_TYPENR(unireg_type),
1369
share->intervals+interval_nr-1 :
1371
share->fieldnames.type_names[i]);
1372
if (!reg_field) // Not supported field type
1375
goto err; /* purecov: inspected */
1378
reg_field->flags|= ((uint32_t)column_format << COLUMN_FORMAT_FLAGS);
1379
reg_field->field_index= i;
1380
reg_field->comment=comment;
1381
reg_field->vcol_info= vcol_info;
1382
reg_field->is_stored= fld_is_stored;
1383
if (!(reg_field->flags & NOT_NULL_FLAG))
1385
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
1388
if (f_no_default(pack_flag))
1389
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
1391
if (reg_field->unireg_check == Field::NEXT_NUMBER)
1392
share->found_next_number_field= field_ptr;
1393
if (share->timestamp_field == reg_field)
1394
share->timestamp_field_offset= i;
1397
(void) my_hash_insert(&share->name_hash,
1398
(unsigned char*) field_ptr); // never fail
1399
if (!reg_field->is_stored)
1401
share->stored_fields--;
1402
if (share->stored_rec_length>=recpos)
1403
share->stored_rec_length= recpos-1;
1406
*field_ptr=0; // End marker
1407
/* Sanity checks: */
1408
assert(share->fields>=share->stored_fields);
1409
assert(share->reclength>=share->stored_rec_length);
1411
/* Fix key->name and key_part->field */
1414
uint32_t primary_key=(uint32_t) (find_type((char*) "PRIMARY",
1415
&share->keynames, 3) - 1);
1416
int64_t ha_option= handler_file->ha_table_flags();
1417
keyinfo= share->key_info;
1418
key_part= keyinfo->key_part;
1420
for (uint32_t key=0 ; key < share->keys ; key++,keyinfo++)
1422
uint32_t usable_parts= 0;
1423
// keyinfo->name=(char*) share->keynames.type_names[key];
1425
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1428
If the UNIQUE key doesn't have NULL columns and is not a part key
1429
declare this as a primary key.
1432
for (i=0 ; i < keyinfo->key_parts ;i++)
1434
uint32_t fieldnr= key_part[i].fieldnr;
1436
share->field[fieldnr-1]->null_ptr ||
1437
share->field[fieldnr-1]->key_length() !=
1440
primary_key=MAX_KEY; // Can't be used
1446
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
1449
if (!key_part->fieldnr)
1451
error= 4; // Wrong file
1454
field= key_part->field= share->field[key_part->fieldnr-1];
1455
key_part->type= field->key_type();
1456
if (field->null_ptr)
1458
key_part->null_offset=(uint32_t) ((unsigned char*) field->null_ptr -
1459
share->default_values);
1460
key_part->null_bit= field->null_bit;
1461
key_part->store_length+=HA_KEY_NULL_LENGTH;
1462
keyinfo->flags|=HA_NULL_PART_KEY;
1463
keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
1464
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
1466
if (field->type() == DRIZZLE_TYPE_BLOB ||
1467
field->real_type() == DRIZZLE_TYPE_VARCHAR)
1469
if (field->type() == DRIZZLE_TYPE_BLOB)
1470
key_part->key_part_flag|= HA_BLOB_PART;
1472
key_part->key_part_flag|= HA_VAR_LENGTH_PART;
1473
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
1474
key_part->store_length+=HA_KEY_BLOB_LENGTH;
1475
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
1477
if (i == 0 && key != primary_key)
1478
field->flags |= (((keyinfo->flags & HA_NOSAME) &&
1479
(keyinfo->key_parts == 1)) ?
1480
UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
1482
field->key_start.set_bit(key);
1483
if (field->key_length() == key_part->length &&
1484
!(field->flags & BLOB_FLAG))
1486
if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
1488
share->keys_for_keyread.set_bit(key);
1489
field->part_of_key.set_bit(key);
1490
field->part_of_key_not_clustered.set_bit(key);
1492
if (handler_file->index_flags(key, i, 1) & HA_READ_ORDER)
1493
field->part_of_sortkey.set_bit(key);
1495
if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
1497
usable_parts++; // For FILESORT
1498
field->flags|= PART_KEY_FLAG;
1499
if (key == primary_key)
1501
field->flags|= PRI_KEY_FLAG;
1503
If this field is part of the primary key and all keys contains
1504
the primary key, then we can use any key to find this column
1506
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
1508
field->part_of_key= share->keys_in_use;
1509
if (field->part_of_sortkey.is_set(key))
1510
field->part_of_sortkey= share->keys_in_use;
1513
if (field->key_length() != key_part->length)
1515
key_part->key_part_flag|= HA_PART_KEY_SEG;
1518
keyinfo->usable_key_parts= usable_parts; // Filesort
1520
set_if_bigger(share->max_key_length,keyinfo->key_length+
1521
keyinfo->key_parts);
1522
share->total_key_length+= keyinfo->key_length;
1524
MERGE tables do not have unique indexes. But every key could be
1525
an unique index on the underlying MyISAM table. (Bug #10400)
1527
if ((keyinfo->flags & HA_NOSAME) ||
1528
(ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
1529
set_if_bigger(share->max_unique_length,keyinfo->key_length);
1531
if (primary_key < MAX_KEY &&
1532
(share->keys_in_use.is_set(primary_key)))
1534
share->primary_key= primary_key;
1536
If we are using an integer as the primary key then allow the user to
1537
refer to it as '_rowid'
1539
if (share->key_info[primary_key].key_parts == 1)
1541
Field *field= share->key_info[primary_key].key_part[0].field;
1542
if (field && field->result_type() == INT_RESULT)
1544
/* note that fieldnr here (and rowid_field_offset) starts from 1 */
1545
share->rowid_field_offset= (share->key_info[primary_key].key_part[0].
1551
share->primary_key = MAX_KEY; // we do not have a primary key
1554
share->primary_key= MAX_KEY;
1558
if (new_field_pack_flag <= 1)
1560
/* Old file format with default as not null */
1561
uint32_t null_length= (share->null_fields+7)/8;
1562
memset(share->default_values + (null_flags - (unsigned char*) record),
1566
if (share->found_next_number_field)
1568
reg_field= *share->found_next_number_field;
1569
if ((int) (share->next_number_index= (uint32_t)
1570
find_ref_key(share->key_info, share->keys,
1571
share->default_values, reg_field,
1572
&share->next_number_key_offset,
1573
&share->next_number_keypart)) < 0)
1575
/* Wrong field definition */
1580
reg_field->flags |= AUTO_INCREMENT_FLAG;
1583
if (share->blob_fields)
1588
/* Store offsets to blob fields to find them fast */
1589
if (!(share->blob_field= save=
1590
(uint*) alloc_root(&share->mem_root,
1591
(uint32_t) (share->blob_fields* sizeof(uint32_t)))))
1593
for (k=0, ptr= share->field ; *ptr ; ptr++, k++)
1595
if ((*ptr)->flags & BLOB_FLAG)
1601
the correct null_bytes can now be set, since bitfields have been taken
1604
share->null_bytes= (null_pos - (unsigned char*) null_flags +
1605
(null_bit_pos + 7) / 8);
1606
share->last_null_bit_pos= null_bit_pos;
1608
share->db_low_byte_first= handler_file->low_byte_first();
1609
share->column_bitmap_size= bitmap_buffer_size(share->fields);
1611
if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1612
share->column_bitmap_size)))
1614
bitmap_init(&share->all_set, bitmaps, share->fields, false);
1615
bitmap_set_all(&share->all_set);
1617
delete handler_file;
1625
share->error= error;
1626
share->open_errno= my_errno;
1627
share->errarg= errarg;
1630
delete handler_file;
1631
hash_free(&share->name_hash);
1633
open_table_error(share, error, share->open_errno, errarg);
1635
} /* open_binary_frm */
1639
Clear flag GET_FIXED_FIELDS_FLAG in all fields of the table.
1640
This routine is used for error handling purposes.
1644
table Table object for which virtual columns are set-up
1649
static void clear_field_flag(Table *table)
1653
for (ptr= table->field; *ptr; ptr++)
1654
(*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
1658
The function uses the feature in fix_fields where the flag
1659
GET_FIXED_FIELDS_FLAG is set for all fields in the item tree.
1660
This field must always be reset before returning from the function
1661
since it is used for other purposes as well.
1664
fix_fields_vcol_func()
1665
session The thread object
1666
func_item The item tree reference of the virtual columnfunction
1667
table The table object
1668
field_name The name of the processed field
1671
true An error occurred, something was wrong with the
1673
false Ok, a partition field array was created
1676
bool fix_fields_vcol_func(Session *session,
1679
const char *field_name)
1681
uint32_t dir_length, home_dir_length;
1684
TableList *save_table_list, *save_first_table, *save_last_table;
1686
Name_resolution_context *context;
1687
const char *save_where;
1689
char db_name_string[FN_REFLEN];
1690
bool save_use_only_table_context;
1691
Field **ptr, *field;
1692
enum_mark_columns save_mark_used_columns= session->mark_used_columns;
1696
Set-up the TABLE_LIST object to be a list with a single table
1697
Set the object to zero to create NULL pointers and set alias
1698
and real name to table name and get database name from file name.
1701
bzero((void*)&tables, sizeof(TableList));
1702
tables.alias= tables.table_name= (char*) table->s->table_name.str;
1703
tables.table= table;
1704
tables.next_local= NULL;
1705
tables.next_name_resolution_table= NULL;
1706
memcpy(db_name_string,
1707
table->s->normalized_path.str,
1708
table->s->normalized_path.length);
1709
dir_length= dirname_length(db_name_string);
1710
db_name_string[dir_length - 1]= 0;
1711
home_dir_length= dirname_length(db_name_string);
1712
db_name= &db_name_string[home_dir_length];
1715
session->mark_used_columns= MARK_COLUMNS_NONE;
1717
context= session->lex->current_context();
1718
table->map= 1; //To ensure correct calculation of const item
1719
table->get_fields_in_item_tree= true;
1720
save_table_list= context->table_list;
1721
save_first_table= context->first_name_resolution_table;
1722
save_last_table= context->last_name_resolution_table;
1723
context->table_list= &tables;
1724
context->first_name_resolution_table= &tables;
1725
context->last_name_resolution_table= NULL;
1726
func_expr->walk(&Item::change_context_processor, 0, (unsigned char*) context);
1727
save_where= session->where;
1728
session->where= "virtual column function";
1730
/* Save the context before fixing the fields*/
1731
save_use_only_table_context= session->lex->use_only_table_context;
1732
session->lex->use_only_table_context= true;
1733
/* Fix fields referenced to by the virtual column function */
1734
error= func_expr->fix_fields(session, (Item**)0);
1735
/* Restore the original context*/
1736
session->lex->use_only_table_context= save_use_only_table_context;
1737
context->table_list= save_table_list;
1738
context->first_name_resolution_table= save_first_table;
1739
context->last_name_resolution_table= save_last_table;
1741
if (unlikely(error))
1743
clear_field_flag(table);
1746
session->where= save_where;
1748
Walk through the Item tree checking if all items are valid
1749
to be part of the virtual column
1751
error= func_expr->walk(&Item::check_vcol_func_processor, 0, NULL);
1754
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
1755
clear_field_flag(table);
1758
if (unlikely(func_expr->const_item()))
1760
my_error(ER_CONST_EXPR_IN_VCOL, MYF(0));
1761
clear_field_flag(table);
1764
/* Ensure that this virtual column is not based on another virtual field. */
1766
while ((field= *(ptr++)))
1768
if ((field->flags & GET_FIXED_FIELDS_FLAG) &&
1771
my_error(ER_VCOL_BASED_ON_VCOL, MYF(0));
1772
clear_field_flag(table);
1777
Cleanup the fields marked with flag GET_FIXED_FIELDS_FLAG
1778
when calling fix_fields.
1780
clear_field_flag(table);
1784
table->get_fields_in_item_tree= false;
1785
session->mark_used_columns= save_mark_used_columns;
1786
table->map= 0; //Restore old value
1791
Unpack the definition of a virtual column
1794
unpack_vcol_info_from_frm()
1795
session Thread handler
1796
table Table with the checked field
1797
field Pointer to Field object
1798
open_mode Open table mode needed to determine
1799
which errors need to be generated in a failure
1800
error_reported updated flag for the caller that no other error
1801
messages are to be generated.
1807
bool unpack_vcol_info_from_frm(Session *session,
1810
LEX_STRING *vcol_expr,
1811
open_table_mode open_mode,
1812
bool *error_reported)
1817
Step 1: Construct a statement for the parser.
1818
The parsed string needs to take the following format:
1819
"PARSE_VCOL_EXPR (<expr_string_from_frm>)"
1821
char *vcol_expr_str;
1824
if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
1826
parse_vcol_keyword.length + 3)))
1830
memcpy(vcol_expr_str,
1831
(char*) parse_vcol_keyword.str,
1832
parse_vcol_keyword.length);
1833
str_len= parse_vcol_keyword.length;
1834
memcpy(vcol_expr_str + str_len, "(", 1);
1836
memcpy(vcol_expr_str + str_len,
1837
(char*) vcol_expr->str,
1839
str_len+= vcol_expr->length;
1840
memcpy(vcol_expr_str + str_len, ")", 1);
1842
memcpy(vcol_expr_str + str_len, "\0", 1);
1844
Lex_input_stream lip(session, vcol_expr_str, str_len);
1847
Step 2: Setup session for parsing.
1848
1) make Item objects be created in the memory allocated for the Table
1849
object (not TABLE_SHARE)
1850
2) ensure that created Item's are not put on to session->free_list
1851
(which is associated with the parsed statement and hence cleared after
1853
3) setup a flag in the LEX structure to allow "PARSE_VCOL_EXPR"
1854
to be parsed as a SQL command.
1856
MEM_ROOT **root_ptr, *old_root;
1857
Item *backup_free_list= session->free_list;
1858
root_ptr= current_mem_root_ptr();
1859
old_root= *root_ptr;
1860
*root_ptr= &table->mem_root;
1861
session->free_list= NULL;
1862
session->lex->parse_vcol_expr= true;
1865
Step 3: Use the parser to build an Item object from.
1867
if (parse_sql(session, &lip))
1871
/* From now on use vcol_info generated by the parser. */
1872
field->vcol_info= session->lex->vcol_info;
1874
/* Validate the Item tree. */
1875
if (fix_fields_vcol_func(session,
1876
field->vcol_info->expr_item,
1880
if (open_mode == OTM_CREATE)
1883
During CREATE/ALTER TABLE it is ok to receive errors here.
1884
It is not ok if it happens during the opening of an frm
1885
file as part of a normal query.
1887
*error_reported= true;
1889
field->vcol_info= NULL;
1892
field->vcol_info->item_free_list= session->free_list;
1893
session->free_list= backup_free_list;
1894
*root_ptr= old_root;
1899
session->lex->parse_vcol_expr= false;
1900
session->free_items();
1901
*root_ptr= old_root;
1902
session->free_list= backup_free_list;
1908
Open a table based on a TABLE_SHARE
1911
open_table_from_share()
1912
session Thread handler
1913
share Table definition
1914
alias Alias for table
1915
db_stat open flags (for example HA_OPEN_KEYFILE|
1916
HA_OPEN_RNDFILE..) can be 0 (example in
1918
prgflag READ_ALL etc..
1919
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
1920
outparam result table
1921
open_mode One of OTM_OPEN|OTM_CREATE|OTM_ALTER
1922
if OTM_CREATE some errors are ignore
1923
if OTM_ALTER HA_OPEN is not called
1927
1 Error (see open_table_error)
1928
2 Error (see open_table_error)
1929
3 Wrong data in .frm file
1930
4 Error (see open_table_error)
1931
5 Error (see open_table_error: charset unavailable)
1932
7 Table definition has changed in engine
1935
int open_table_from_share(Session *session, TABLE_SHARE *share, const char *alias,
1936
uint32_t db_stat, uint32_t prgflag, uint32_t ha_open_flags,
1937
Table *outparam, open_table_mode open_mode)
1940
uint32_t records, i, bitmap_size;
1941
bool error_reported= false;
1942
unsigned char *record, *bitmaps;
1943
Field **field_ptr, **vfield_ptr;
1945
/* Parsing of partitioning information from .frm needs session->lex set up. */
1946
assert(session->lex->is_lex_started);
1949
memset(outparam, 0, sizeof(*outparam));
1950
outparam->in_use= session;
1952
outparam->db_stat= db_stat;
1953
outparam->write_row_record= NULL;
1955
init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
1957
if (!(outparam->alias= strdup(alias)))
1959
outparam->quick_keys.init();
1960
outparam->covering_keys.init();
1961
outparam->keys_in_use_for_query.init();
1963
/* Allocate handler */
1965
if (!(prgflag & OPEN_FRM_FILE_ONLY))
1967
if (!(outparam->file= get_new_handler(share, &outparam->mem_root,
1977
outparam->reginfo.lock_type= TL_UNLOCK;
1978
outparam->current_lock= F_UNLCK;
1980
if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
1982
if (prgflag & (READ_ALL+EXTRA_RECORD))
1985
if (!(record= (unsigned char*) alloc_root(&outparam->mem_root,
1986
share->rec_buff_length * records)))
1987
goto err; /* purecov: inspected */
1991
/* We are probably in hard repair, and the buffers should not be used */
1992
outparam->record[0]= outparam->record[1]= share->default_values;
1996
outparam->record[0]= record;
1998
outparam->record[1]= record+ share->rec_buff_length;
2000
outparam->record[1]= outparam->record[0]; // Safety
2005
We need this because when we read var-length rows, we are not updating
2006
bytes after end of varchar
2010
memcpy(outparam->record[0], share->default_values, share->rec_buff_length);
2011
memcpy(outparam->record[1], share->default_values, share->null_bytes);
2013
memcpy(outparam->record[1], share->default_values,
2014
share->rec_buff_length);
2018
if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root,
2019
(uint32_t) ((share->fields+1)*
2021
goto err; /* purecov: inspected */
2023
outparam->field= field_ptr;
2025
record= (unsigned char*) outparam->record[0]-1; /* Fieldstart = 1 */
2027
outparam->null_flags= (unsigned char*) record+1;
2029
/* Setup copy of fields from share, but use the right alias and record */
2030
for (i=0 ; i < share->fields; i++, field_ptr++)
2032
if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam)))
2035
(*field_ptr)= 0; // End marker
2037
if (share->found_next_number_field)
2038
outparam->found_next_number_field=
2039
outparam->field[(uint32_t) (share->found_next_number_field - share->field)];
2040
if (share->timestamp_field)
2041
outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
2044
/* Fix key->name and key_part->field */
2045
if (share->key_parts)
2047
KEY *key_info, *key_info_end;
2048
KEY_PART_INFO *key_part;
2050
n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO);
2051
if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length)))
2053
outparam->key_info= key_info;
2054
key_part= (reinterpret_cast<KEY_PART_INFO*> (key_info+share->keys));
2056
memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
2057
memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) *
2060
for (key_info_end= key_info + share->keys ;
2061
key_info < key_info_end ;
2064
KEY_PART_INFO *key_part_end;
2066
key_info->table= outparam;
2067
key_info->key_part= key_part;
2069
for (key_part_end= key_part+ key_info->key_parts ;
2070
key_part < key_part_end ;
2073
Field *field= key_part->field= outparam->field[key_part->fieldnr-1];
2075
if (field->key_length() != key_part->length &&
2076
!(field->flags & BLOB_FLAG))
2079
We are using only a prefix of the column as a key:
2080
Create a new field for the key part that matches the index
2082
field= key_part->field=field->new_field(&outparam->mem_root,
2084
field->field_length= key_part->length;
2091
Process virtual columns, if any.
2093
if (not (vfield_ptr = (Field **) alloc_root(&outparam->mem_root,
2094
(uint32_t) ((share->vfields+1)*
2098
outparam->vfield= vfield_ptr;
2100
for (field_ptr= outparam->field; *field_ptr; field_ptr++)
2102
if ((*field_ptr)->vcol_info)
2104
if (unpack_vcol_info_from_frm(session,
2107
&(*field_ptr)->vcol_info->expr_str,
2111
error= 4; // in case no error is reported
2114
*(vfield_ptr++)= *field_ptr;
2117
*vfield_ptr= NULL; // End marker
2118
/* Check virtual columns against table's storage engine. */
2119
if ((share->vfields && outparam->file) &&
2120
(not outparam->file->check_if_supported_virtual_columns()))
2122
my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN,
2124
"Specified storage engine");
2125
error_reported= true;
2129
/* Allocate bitmaps */
2131
bitmap_size= share->column_bitmap_size;
2132
if (!(bitmaps= (unsigned char*) alloc_root(&outparam->mem_root, bitmap_size*3)))
2134
bitmap_init(&outparam->def_read_set,
2135
(my_bitmap_map*) bitmaps, share->fields, false);
2136
bitmap_init(&outparam->def_write_set,
2137
(my_bitmap_map*) (bitmaps+bitmap_size), share->fields, false);
2138
bitmap_init(&outparam->tmp_set,
2139
(my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, false);
2140
outparam->default_column_bitmaps();
2142
/* The table struct is now initialized; Open the table */
2144
if (db_stat && open_mode != OTM_ALTER)
2147
if ((ha_err= (outparam->file->
2148
ha_open(outparam, share->normalized_path.str,
2149
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
2150
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
2151
(db_stat & HA_WAIT_IF_LOCKED) ? HA_OPEN_WAIT_IF_LOCKED :
2152
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
2153
HA_OPEN_ABORT_IF_LOCKED :
2154
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
2156
/* Set a flag if the table is crashed and it can be auto. repaired */
2157
share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
2158
outparam->file->auto_repair() &&
2159
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
2163
case HA_ERR_NO_SUCH_TABLE:
2165
The table did not exists in storage engine, use same error message
2166
as if the .frm file didn't exist
2173
Too many files opened, use same error message as if the .frm
2180
outparam->file->print_error(ha_err, MYF(0));
2181
error_reported= true;
2182
if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
2186
goto err; /* purecov: inspected */
2190
#if defined(HAVE_purify)
2191
memset(bitmaps, 0, bitmap_size*3);
2194
outparam->no_replicate= outparam->file;
2195
session->status_var.opened_tables++;
2200
if (!error_reported && !(prgflag & DONT_GIVE_ERROR))
2201
open_table_error(share, error, my_errno, 0);
2202
delete outparam->file;
2203
outparam->file= 0; // For easier error checking
2204
outparam->db_stat=0;
2205
free_root(&outparam->mem_root, MYF(0)); // Safe to call on zeroed root
2206
free((char*) outparam->alias);
2210
/* close_temporary_tables' internal, 4 is due to uint4korr definition */
2211
uint32_t Table::tmpkeyval()
2213
return uint4korr(s->table_cache_key.str + s->table_cache_key.length - 4);
2217
Free information allocated by openfrm
2221
table Table object to free
2222
free_share Is 1 if we also want to free table_share
2225
int Table::closefrm(bool free_share)
82
error= cursor->close();
2230
error= file->close();
2231
free((char*) alias);
87
2235
for (Field **ptr=field ; *ptr ; ptr++)
94
cursor= 0; /* For easier errorchecking */
2240
file= 0; /* For easier errorchecking */
2243
if (s->tmp_table == NO_TMP_TABLE)
2244
release_table_share(s, RELEASE_NORMAL);
2246
free_table_share(s);
2248
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
2254
/* Deallocate temporary blob storage */
1398
4702
session->mem_root= mem_root_save;
4703
table->free_tmp_table(session); /* purecov: inspected */
4704
if (temp_pool_slot != MY_BIT_NONE)
4705
bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
4706
return(NULL); /* purecov: inspected */
1404
4709
/****************************************************************************/
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;
4712
Create a reduced Table object with properly set up Field list from a
4713
list of field definitions.
4715
The created table doesn't have a table handler associated with
4716
it, has no keys, no group/distinct, no copy_funcs array.
4717
The sole purpose of this Table object is to use the power of Field
4718
class to read/write data to/from table->record[0]. Then one can store
4719
the record in any container (RB tree, hash, etc).
4720
The table is created in Session mem_root, so are the table's fields.
4721
Consequently, if you don't BLOB fields, you don't need to free it.
4723
@param session connection handle
4724
@param field_list list of column definitions
4727
0 if out of memory, Table object in case of success
4730
Table *create_virtual_tmp_table(Session *session, List<Create_field> &field_list)
4732
uint32_t field_count= field_list.elements;
4733
uint32_t blob_count= 0;
4735
Create_field *cdef; /* column definition */
4736
uint32_t record_length= 0;
4737
uint32_t null_count= 0; /* number of columns which may be null */
4738
uint32_t null_pack_length; /* NULL representation array length */
4739
uint32_t *blob_field;
4740
unsigned char *bitmaps;
4744
if (!multi_alloc_root(session->mem_root,
4745
&table, sizeof(*table),
4746
&share, sizeof(*share),
4747
&field, (field_count + 1) * sizeof(Field*),
4748
&blob_field, (field_count+1) *sizeof(uint32_t),
4749
&bitmaps, bitmap_buffer_size(field_count)*2,
4753
memset(table, 0, sizeof(*table));
4754
memset(share, 0, sizeof(*share));
4755
table->field= field;
4757
share->blob_field= blob_field;
4758
share->fields= field_count;
4759
share->blob_ptr_size= portable_sizeof_char_ptr;
4760
table->setup_tmp_table_column_bitmaps(bitmaps);
4762
/* Create all fields and calculate the total length of record */
4763
List_iterator_fast<Create_field> it(field_list);
4764
while ((cdef= it++))
4766
*field= make_field(share, 0, cdef->length,
4767
(unsigned char*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
4768
f_maybe_null(cdef->pack_flag) ? 1 : 0,
4769
cdef->pack_flag, cdef->sql_type, cdef->charset,
4771
cdef->interval, cdef->field_name);
4774
(*field)->init(table);
4775
record_length+= (*field)->pack_length();
4776
if (! ((*field)->flags & NOT_NULL_FLAG))
4779
if ((*field)->flags & BLOB_FLAG)
4780
share->blob_field[blob_count++]= (uint32_t) (field - table->field);
4784
*field= NULL; /* mark the end of the list */
4785
share->blob_field[blob_count]= 0; /* mark the end of the list */
4786
share->blob_fields= blob_count;
4788
null_pack_length= (null_count + 7)/8;
4789
share->reclength= record_length + null_pack_length;
4790
share->rec_buff_length= ALIGN_SIZE(share->reclength + 1);
4791
table->record[0]= (unsigned char*) session->alloc(share->rec_buff_length);
4792
if (!table->record[0])
4795
if (null_pack_length)
4797
table->null_flags= (unsigned char*) table->record[0];
4798
share->null_fields= null_count;
4799
share->null_bytes= null_pack_length;
4802
table->in_use= session; /* field->reset() may access table->in_use */
4804
/* Set up field pointers */
4805
unsigned char *null_pos= table->record[0];
4806
unsigned char *field_pos= null_pos + share->null_bytes;
4807
uint32_t null_bit= 1;
4809
for (field= table->field; *field; ++field)
4811
Field *cur_field= *field;
4812
if ((cur_field->flags & NOT_NULL_FLAG))
4813
cur_field->move_field(field_pos);
4816
cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
4818
if (null_bit == (1 << 8))
4826
field_pos+= cur_field->pack_length();
4831
for (field= table->field; *field; ++field)
4832
delete *field; /* just invokes field destructor */
4837
bool Table::open_tmp_table()
4840
if ((error=file->ha_open(this, s->table_name.str,O_RDWR,
4841
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
4843
file->print_error(error,MYF(0)); /* purecov: inspected */
4847
(void) file->extra(HA_EXTRA_QUICK); /* Faster */
4853
Create MyISAM temporary table
4856
create_myisam_tmp_table()
4857
keyinfo Description of the index (there is always one index)
4858
start_recinfo MyISAM's column descriptions
4859
recinfo INOUT End of MyISAM's column descriptions
4863
Create a MyISAM temporary table according to passed description. The is
4864
assumed to have one unique index or constraint.
4866
The passed array or MI_COLUMNDEF structures must have this form:
4868
1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
4869
when there are many nullable columns)
4871
3. One free MI_COLUMNDEF element (*recinfo points here)
4873
This function may use the free element to create hash column for unique
4881
bool Table::create_myisam_tmp_table(KEY *keyinfo,
4882
MI_COLUMNDEF *start_recinfo,
4883
MI_COLUMNDEF **recinfo,
4888
MI_UNIQUEDEF uniquedef;
4889
TABLE_SHARE *share= s;
4892
{ // Get keys for ni_create
4893
bool using_unique_constraint=0;
4894
HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&this->mem_root,
4895
sizeof(*seg) * keyinfo->key_parts);
4899
memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
4900
if (keyinfo->key_length >= file->max_key_length() ||
4901
keyinfo->key_parts > file->max_key_parts() ||
4904
/* Can't create a key; Make a unique constraint instead of a key */
4907
using_unique_constraint=1;
4908
memset(&uniquedef, 0, sizeof(uniquedef));
4909
uniquedef.keysegs=keyinfo->key_parts;
4911
uniquedef.null_are_equal=1;
4913
/* Create extra column for hash value */
4914
memset(*recinfo, 0, sizeof(**recinfo));
4915
(*recinfo)->type= FIELD_CHECK;
4916
(*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
4918
share->reclength+=MI_UNIQUE_HASH_LENGTH;
4922
/* Create an unique key */
4923
memset(&keydef, 0, sizeof(keydef));
4924
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
4925
keydef.keysegs= keyinfo->key_parts;
4928
for (uint32_t i=0; i < keyinfo->key_parts ; i++,seg++)
4930
Field *key_field=keyinfo->key_part[i].field;
4932
seg->language= key_field->charset()->number;
4933
seg->length= keyinfo->key_part[i].length;
4934
seg->start= keyinfo->key_part[i].offset;
4935
if (key_field->flags & BLOB_FLAG)
4938
((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
4939
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
4940
seg->bit_start= (uint8_t)(key_field->pack_length()
4941
- share->blob_ptr_size);
4942
seg->flag= HA_BLOB_PART;
4943
seg->length=0; // Whole blob in unique constraint
4947
seg->type= keyinfo->key_part[i].type;
4949
if (!(key_field->flags & NOT_NULL_FLAG))
4951
seg->null_bit= key_field->null_bit;
4952
seg->null_pos= (uint32_t) (key_field->null_ptr - (unsigned char*) record[0]);
4954
We are using a GROUP BY on something that contains NULL
4955
In this case we have to tell MyISAM that two NULL should
4956
on INSERT be regarded at the same value
4958
if (!using_unique_constraint)
4959
keydef.flag|= HA_NULL_ARE_EQUAL;
4963
MI_CREATE_INFO create_info;
4964
memset(&create_info, 0, sizeof(create_info));
4966
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
4968
create_info.data_file_length= ~(uint64_t) 0;
4970
if ((error=mi_create(share->table_name.str, share->keys, &keydef,
4971
(uint32_t) (*recinfo-start_recinfo),
4973
share->uniques, &uniquedef,
4975
HA_CREATE_TMP_TABLE)))
4977
file->print_error(error,MYF(0)); /* purecov: inspected */
4981
status_var_increment(in_use->status_var.created_tmp_disk_tables);
4982
share->db_record_offset= 1;
4989
void Table::free_tmp_table(Session *session)
4991
MEM_ROOT own_root= mem_root;
4992
const char *save_proc_info;
4994
save_proc_info=session->get_proc_info();
4995
session->set_proc_info("removing tmp table");
4997
// Release latches since this can take a long time
4998
ha_release_temporary_latches(session);
5003
file->ha_drop_table(s->table_name.str);
5005
file->ha_delete_table(s->table_name.str);
5010
for (Field **ptr= field ; *ptr ; ptr++)
5012
free_io_cache(this);
5014
if (temp_pool_slot != MY_BIT_NONE)
5015
bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
5017
plugin_unlock(0, s->db_plugin);
5019
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
5020
session->set_proc_info(save_proc_info);
5026
If a HEAP table gets full, create a MyISAM table and copy all rows
5030
bool create_myisam_from_heap(Session *session, Table *table,
5031
MI_COLUMNDEF *start_recinfo,
5032
MI_COLUMNDEF **recinfo,
5033
int error, bool ignore_last_dupp_key_error)
5037
const char *save_proc_info;
5040
if (table->s->db_type() != heap_hton ||
5041
error != HA_ERR_RECORD_FILE_FULL)
5043
table->file->print_error(error,MYF(0));
5047
// Release latches since this can take a long time
5048
ha_release_temporary_latches(session);
5052
new_table.s= &share;
5053
new_table.s->db_plugin= ha_lock_engine(session, myisam_hton);
5054
if (!(new_table.file= get_new_handler(&share, &new_table.mem_root,
5055
new_table.s->db_type())))
5056
return(1); // End of memory
5058
save_proc_info=session->get_proc_info();
5059
session->set_proc_info("converting HEAP to MyISAM");
5061
if (new_table.create_myisam_tmp_table(table->key_info, start_recinfo,
5062
recinfo, session->lex->select_lex.options |
5065
if (new_table.open_tmp_table())
5067
if (table->file->indexes_are_disabled())
5068
new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
5069
table->file->ha_index_or_rnd_end();
5070
table->file->ha_rnd_init(1);
5073
new_table.file->extra(HA_EXTRA_NO_ROWS);
5074
new_table.no_rows=1;
5077
/* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
5078
new_table.file->extra(HA_EXTRA_WRITE_CACHE);
5081
copy all old rows from heap table to MyISAM table
5082
This is the only code that uses record[1] to read/write but this
5083
is safe as this is a temporary MyISAM table without timestamp/autoincrement.
5085
while (!table->file->rnd_next(new_table.record[1]))
5087
write_err= new_table.file->ha_write_row(new_table.record[1]);
5091
/* copy row that filled HEAP table */
5092
if ((write_err=new_table.file->ha_write_row(table->record[0])))
5094
if (new_table.file->is_fatal_error(write_err, HA_CHECK_DUP) ||
5095
!ignore_last_dupp_key_error)
5099
/* remove heap table and change to use myisam table */
5100
(void) table->file->ha_rnd_end();
5101
(void) table->file->close(); // This deletes the table !
5104
plugin_unlock(0, table->s->db_plugin);
5105
share.db_plugin= my_plugin_lock(0, &share.db_plugin);
5106
new_table.s= table->s; // Keep old share
5110
table->file->change_table_ptr(table, table->s);
5111
table->use_all_columns();
5114
const char *new_proc_info=
5115
(!strcmp(save_proc_info,"Copying to tmp table") ?
5116
"Copying to tmp table on disk" : save_proc_info);
5117
session->set_proc_info(new_proc_info);
5122
table->file->print_error(write_err, MYF(0));
5123
(void) table->file->ha_rnd_end();
5124
(void) new_table.file->close();
5126
new_table.file->ha_delete_table(new_table.s->table_name.str);
5128
delete new_table.file;
5129
session->set_proc_info(save_proc_info);
5130
table->mem_root= new_table.mem_root;
5134
my_bitmap_map *Table::use_all_columns(MY_BITMAP *bitmap)
5136
my_bitmap_map *old= bitmap->bitmap;
5137
bitmap->bitmap= s->all_set.bitmap;
1421
void Table::restore_column_map(const boost::dynamic_bitset<>& old)
5141
void Table::restore_column_map(my_bitmap_map *old)
1423
for (boost::dynamic_bitset<>::size_type i= 0; i < old.size(); i++)
5143
read_set->bitmap= old;
1436
5146
uint32_t Table::find_shortest_key(const key_map *usable_keys)
1438
5148
uint32_t min_length= UINT32_MAX;
1439
5149
uint32_t best= MAX_KEY;
1440
if (usable_keys->any())
5150
if (!usable_keys->is_clear_all())
1442
for (uint32_t nr= 0; nr < getShare()->sizeKeys() ; nr++)
5152
for (uint32_t nr=0; nr < s->keys ; nr++)
1444
if (usable_keys->test(nr))
5154
if (usable_keys->is_set(nr))
1446
5156
if (key_info[nr].key_length < min_length)