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 */
28
#include <drizzled/error.h>
29
#include <drizzled/gettext.h>
31
#include <drizzled/plugin/transactional_storage_engine.h>
32
#include <drizzled/plugin/authorization.h>
33
#include <drizzled/nested_join.h>
34
#include <drizzled/sql_parse.h>
35
#include <drizzled/item/sum.h>
36
#include <drizzled/table_list.h>
37
#include <drizzled/session.h>
38
#include <drizzled/sql_base.h>
39
#include <drizzled/sql_select.h>
40
#include <drizzled/field/blob.h>
41
#include <drizzled/field/varstring.h>
42
#include <drizzled/field/double.h>
43
#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>
63
#include <drizzled/typelib.h>
70
extern plugin::StorageEngine *heap_engine;
71
extern plugin::StorageEngine *myisam_engine;
73
/* Functions defined in this cursor */
19
#include <drizzled/server_includes.h>
20
#include <drizzled/drizzled_error_messages.h>
22
#include "tmp_table.h"
23
#include "sj_tmp_table.h"
25
/* INFORMATION_SCHEMA name */
26
LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")};
28
/* Keyword for parsing virtual column functions */
29
LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
31
/* Functions defined in this file */
33
void open_table_error(TABLE_SHARE *share, int error, int db_errno,
34
myf errortype, int errarg);
35
static int open_binary_frm(THD *thd, TABLE_SHARE *share,
36
unsigned char *head, File file);
37
static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
38
uint32_t types, char **names);
39
static uint32_t find_field(Field **fields, unsigned char *record, uint32_t start, uint32_t length);
75
41
/*************************************************************************/
77
// @note this should all be the destructor
78
int Table::delete_table(bool free_share)
83
error= cursor->close();
88
for (Field **ptr=field ; *ptr ; ptr++)
43
/* Get column name from column hash */
45
static unsigned char *get_field_name(Field **buff, size_t *length,
46
bool not_used __attribute__((unused)))
48
*length= (uint) strlen((*buff)->field_name);
49
return (unsigned char*) (*buff)->field_name;
54
Returns pointer to '.frm' extension of the file name.
61
Checks file name part starting with the rightmost '.' character,
62
and returns it if it is equal to '.frm'.
65
It is a good idea to get rid of this function modifying the code
66
to garantee that the functions presently calling fn_rext() always
67
get arguments in the same format: either with '.frm' or without '.frm'.
70
Pointer to the '.frm' extension. If there is no extension,
71
or extension is not '.frm', pointer at the end of file name.
74
char *fn_rext(char *name)
76
char *res= strrchr(name, '.');
77
if (res && !strcmp(res, reg_ext))
79
return name + strlen(name);
82
TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name)
87
if ((db->length == INFORMATION_SCHEMA_NAME.length) &&
88
(my_strcasecmp(system_charset_info,
89
INFORMATION_SCHEMA_NAME.str,
92
return TABLE_CATEGORY_INFORMATION;
95
return TABLE_CATEGORY_USER;
100
Allocate a setup TABLE_SHARE structure
104
TableList Take database and table name from there
105
key Table cache key (db \0 table_name \0...)
106
key_length Length of key
109
0 Error (out of memory)
113
TABLE_SHARE *alloc_table_share(TableList *table_list, char *key,
118
char *key_buff, *path_buff;
119
char path[FN_REFLEN];
120
uint32_t path_length;
122
path_length= build_table_filename(path, sizeof(path) - 1,
124
table_list->table_name, "", 0);
125
init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
126
if (multi_alloc_root(&mem_root,
127
&share, sizeof(*share),
128
&key_buff, key_length,
129
&path_buff, path_length + 1,
132
memset(share, 0, sizeof(*share));
134
share->set_table_cache_key(key_buff, key, key_length);
136
share->path.str= path_buff;
137
share->path.length= path_length;
138
my_stpcpy(share->path.str, path);
139
share->normalized_path.str= share->path.str;
140
share->normalized_path.length= path_length;
142
share->version= refresh_version;
145
This constant is used to mark that no table map version has been
146
assigned. No arithmetic is done on the value: it will be
147
overwritten with a value taken from DRIZZLE_BIN_LOG.
149
share->table_map_version= UINT64_MAX;
152
Since alloc_table_share() can be called without any locking (for
153
example, ha_create_table... functions), we do not assign a table
154
map id here. Instead we assign a value that is not used
155
elsewhere, and then assign a table map id inside open_table()
156
under the protection of the LOCK_open mutex.
158
share->table_map_id= UINT32_MAX;
159
share->cached_row_logging_check= -1;
161
memcpy(&share->mem_root, &mem_root, sizeof(mem_root));
162
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
163
pthread_cond_init(&share->cond, NULL);
170
Initialize share for temporary tables
173
init_tmp_table_share()
176
key Table_cache_key, as generated from create_table_def_key.
177
must start with db name.
178
key_length Length of key
179
table_name Table name
180
path Path to file (possible in lower case) without .frm
183
This is different from alloc_table_share() because temporary tables
184
don't have to be shared between threads or put into the table def
185
cache, so we can do some things notable simpler and faster
187
If table is not put in thd->temporary_tables (happens only when
188
one uses OPEN TEMPORARY) then one can specify 'db' as key and
189
use key_length= 0 as neither table_cache_key or key_length will be used).
192
void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,
193
uint32_t key_length, const char *table_name,
197
memset(share, 0, sizeof(*share));
198
init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
199
share->table_category= TABLE_CATEGORY_TEMPORARY;
200
share->tmp_table= INTERNAL_TMP_TABLE;
201
share->db.str= (char*) key;
202
share->db.length= strlen(key);
203
share->table_cache_key.str= (char*) key;
204
share->table_cache_key.length= key_length;
205
share->table_name.str= (char*) table_name;
206
share->table_name.length= strlen(table_name);
207
share->path.str= (char*) path;
208
share->normalized_path.str= (char*) path;
209
share->path.length= share->normalized_path.length= strlen(path);
210
share->frm_version= FRM_VER_TRUE_VARCHAR;
212
Temporary tables are not replicated, but we set up these fields
213
anyway to be able to catch errors.
215
share->table_map_version= ~(uint64_t)0;
216
share->cached_row_logging_check= -1;
219
table_map_id is also used for MERGE tables to suppress repeated
220
compatibility checks.
222
share->table_map_id= (ulong) thd->query_id;
229
Free table share and memory used by it
236
share->mutex must be locked when we come here if it's not a temp table
239
void free_table_share(TABLE_SHARE *share)
242
assert(share->ref_count == 0);
245
If someone is waiting for this to be deleted, inform it about this.
246
Don't do a delete until we know that no one is refering to this anymore.
248
if (share->tmp_table == NO_TMP_TABLE)
250
/* share->mutex is locked in release_table_share() */
251
while (share->waiting_on_cond)
253
pthread_cond_broadcast(&share->cond);
254
pthread_cond_wait(&share->cond, &share->mutex);
256
/* No thread refers to this anymore */
257
pthread_mutex_unlock(&share->mutex);
258
pthread_mutex_destroy(&share->mutex);
259
pthread_cond_destroy(&share->cond);
261
hash_free(&share->name_hash);
263
plugin_unlock(NULL, share->db_plugin);
264
share->db_plugin= NULL;
266
/* We must copy mem_root from share because share is allocated through it */
267
memcpy(&mem_root, &share->mem_root, sizeof(mem_root));
268
free_root(&mem_root, MYF(0)); // Free's share
273
Read table definition from a binary / text based .frm file
278
share Fill this with table definition
279
db_flags Bit mask of the following flags: OPEN_VIEW
282
This function is called when the table definition is not cached in
284
The data is returned in 'share', which is alloced by
285
alloc_table_share().. The code assumes that share is initialized.
289
1 Error (see open_table_error)
290
2 Error (see open_table_error)
291
3 Wrong data in .frm file
292
4 Error (see open_table_error)
293
5 Error (see open_table_error: charset unavailable)
294
6 Unknown .frm version
297
int open_table_def(THD *thd, TABLE_SHARE *share, uint32_t db_flags __attribute__((unused)))
299
int error, table_type;
302
unsigned char head[64], *disk_buff;
303
char path[FN_REFLEN];
304
MEM_ROOT **root_ptr, *old_root;
310
strxmov(path, share->normalized_path.str, reg_ext, NULL);
311
if ((file= open(path, O_RDONLY)) < 0)
314
We don't try to open 5.0 unencoded name, if
315
- non-encoded name contains '@' signs,
316
because '@' can be misinterpreted.
317
It is not clear if '@' is escape character in 5.1,
318
or a normal character in 5.0.
320
- non-encoded db or table name contain "#mysql50#" prefix.
321
This kind of tables must have been opened only by the
324
if (strchr(share->table_name.str, '@') ||
325
!strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX,
326
MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
327
!strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX,
328
MYSQL50_TABLE_NAME_PREFIX_LENGTH))
331
/* Try unencoded 5.0 name */
333
strxnmov(path, sizeof(path)-1,
334
mysql_data_home, "/", share->db.str, "/",
335
share->table_name.str, reg_ext, NULL);
336
length= unpack_filename(path, path) - reg_ext_length;
338
The following is a safety test and should never fail
339
as the old file name should never be longer than the new one.
341
assert(length <= share->normalized_path.length);
343
If the old and the new names have the same length,
344
then table name does not have tricky characters,
345
so no need to check the old file name.
347
if (length == share->normalized_path.length ||
348
((file= open(path, O_RDONLY)) < 0))
351
/* Unencoded 5.0 table name found */
352
path[length]= '\0'; // Remove .frm extension
353
my_stpcpy(share->normalized_path.str, path);
354
share->normalized_path.length= length;
358
if (my_read(file, head, 64, MYF(MY_NABP)))
361
if (head[0] == (unsigned char) 254 && head[1] == 1)
363
if (head[2] == FRM_VER || head[2] == FRM_VER+1 ||
364
(head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4))
370
error= 6; // Unkown .frm version
377
/* No handling of text based files yet */
380
root_ptr= (MEM_ROOT **)pthread_getspecific(THR_MALLOC);
382
*root_ptr= &share->mem_root;
383
error= open_binary_frm(thd, share, head, file);
390
share->table_category= get_table_category(& share->db, & share->table_name);
393
thd->status_var.opened_shares++;
396
my_close(file, MYF(MY_WME));
399
if (error && !error_given)
402
open_table_error(share, error, (share->open_errno= my_errno), 0);
410
Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
413
static int open_binary_frm(THD *thd, TABLE_SHARE *share, unsigned char *head,
416
int error, errarg= 0;
417
uint32_t new_frm_ver, field_pack_length, new_field_pack_flag;
418
uint32_t interval_count, interval_parts, read_length, int_length;
419
uint32_t db_create_options, keys, key_parts, n_length;
420
uint32_t key_info_length, com_length, null_bit_pos=0;
421
uint32_t vcol_screen_length;
422
uint32_t extra_rec_buf_length;
425
unsigned char forminfo[288];
426
char *keynames, *names, *comment_pos, *vcol_screen_pos;
427
unsigned char *record;
428
unsigned char *disk_buff, *strpos, *null_flags=NULL, *null_pos=NULL;
429
ulong pos, record_offset, *rec_per_key, rec_buff_length;
430
handler *handler_file= 0;
432
KEY_PART_INFO *key_part;
433
Field **field_ptr, *reg_field;
434
const char **interval_array;
435
enum legacy_db_type legacy_db_type;
436
my_bitmap_map *bitmaps;
437
unsigned char *buff= 0;
438
unsigned char *field_extra_info= 0;
440
new_field_pack_flag= head[27];
441
new_frm_ver= (head[2] - FRM_VER);
442
field_pack_length= new_frm_ver < 2 ? 11 : 17;
446
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
447
goto err; /* purecov: inspected */
448
my_seek(file,pos,MY_SEEK_SET,MYF(0));
449
if (my_read(file,forminfo,288,MYF(MY_NABP)))
452
share->frm_version= head[2];
454
Check if .frm file created by MySQL 5.0. In this case we want to
455
display CHAR fields as CHAR and not as VARCHAR.
456
We do it this way as we want to keep the old frm version to enable
457
MySQL 4.1 to read these files.
459
if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5)
460
share->frm_version= FRM_VER_TRUE_VARCHAR;
462
legacy_db_type= DB_TYPE_FIRST_DYNAMIC;
463
assert(share->db_plugin == NULL);
465
if the storage engine is dynamic, no point in resolving it by its
466
dynamically allocated legacy_db_type. We will resolve it later by name.
468
if (legacy_db_type > DB_TYPE_UNKNOWN &&
469
legacy_db_type < DB_TYPE_FIRST_DYNAMIC)
470
share->db_plugin= ha_lock_engine(NULL,
471
ha_checktype(thd, legacy_db_type, 0, 0));
472
share->db_create_options= db_create_options= uint2korr(head+30);
473
share->db_options_in_use= share->db_create_options;
474
share->mysql_version= uint4korr(head+51);
475
share->null_field_first= 0;
476
if (!head[32]) // New frm file in 3.23
478
share->avg_row_length= uint4korr(head+34);
479
share->transactional= (ha_choice) (head[39] & 3);
480
share->page_checksum= (ha_choice) ((head[39] >> 2) & 3);
481
share->row_type= (row_type) head[40];
482
share->block_size= uint4korr(head+43);
483
share->table_charset= get_charset((uint) head[38],MYF(0));
484
share->null_field_first= 1;
486
if (!share->table_charset)
488
/* unknown charset in head[38] or pre-3.23 frm */
489
if (use_mb(default_charset_info))
491
/* Warn that we may be changing the size of character columns */
492
sql_print_warning(_("'%s' had no or invalid character set, "
493
"and default character set is multi-byte, "
494
"so character column sizes may have changed"),
497
share->table_charset= default_charset_info;
499
share->db_record_offset= 1;
500
if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
501
share->blob_ptr_size= portable_sizeof_char_ptr;
502
/* Set temporarily a good value for db_low_byte_first */
503
share->db_low_byte_first= true;
505
share->max_rows= uint4korr(head+18);
506
share->min_rows= uint4korr(head+22);
508
/* Read keyinformation */
509
key_info_length= (uint) uint2korr(head+28);
510
my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0));
511
if (read_string(file,(unsigned char**) &disk_buff,key_info_length))
512
goto err; /* purecov: inspected */
513
if (disk_buff[0] & 0x80)
515
share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
516
share->key_parts= key_parts= uint2korr(disk_buff+2);
520
share->keys= keys= disk_buff[0];
521
share->key_parts= key_parts= disk_buff[1];
523
share->keys_for_keyread.init(0);
524
share->keys_in_use.init(keys);
526
n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
527
if (!(keyinfo = (KEY*) alloc_root(&share->mem_root,
528
n_length + uint2korr(disk_buff+4))))
529
goto err; /* purecov: inspected */
530
memset(keyinfo, 0, n_length);
531
share->key_info= keyinfo;
532
key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo+keys);
535
if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
536
sizeof(ulong*)*key_parts)))
539
for (i=0 ; i < keys ; i++, keyinfo++)
541
keyinfo->table= 0; // Updated in open_frm
542
if (new_frm_ver >= 3)
544
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
545
keyinfo->key_length= (uint) uint2korr(strpos+2);
546
keyinfo->key_parts= (uint) strpos[4];
547
keyinfo->algorithm= (enum ha_key_alg) strpos[5];
548
keyinfo->block_size= uint2korr(strpos+6);
552
keyinfo->key_part= key_part;
553
keyinfo->rec_per_key= rec_per_key;
554
for (j=keyinfo->key_parts ; j-- ; key_part++)
557
key_part->fieldnr= (uint16_t) (uint2korr(strpos) & FIELD_NR_MASK);
558
key_part->offset= (uint) uint2korr(strpos+2)-1;
559
key_part->key_type= (uint) uint2korr(strpos+5);
560
// key_part->field= (Field*) 0; // Will be fixed later
561
if (new_frm_ver >= 1)
563
key_part->key_part_flag= *(strpos+4);
564
key_part->length= (uint) uint2korr(strpos+7);
569
key_part->length= *(strpos+4);
570
key_part->key_part_flag=0;
571
if (key_part->length > 128)
573
key_part->length&=127; /* purecov: inspected */
574
key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
578
key_part->store_length=key_part->length;
581
keynames=(char*) key_part;
582
strpos+= (my_stpcpy(keynames, (char *) strpos) - keynames)+1;
584
//reading index comments
585
for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
587
if (keyinfo->flags & HA_USES_COMMENT)
589
keyinfo->comment.length= uint2korr(strpos);
590
keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos+2,
591
keyinfo->comment.length);
592
strpos+= 2 + keyinfo->comment.length;
594
assert(test(keyinfo->flags & HA_USES_COMMENT) ==
595
(keyinfo->comment.length > 0));
598
share->reclength = uint2korr((head+16));
599
share->stored_rec_length= share->reclength;
601
record_offset= (ulong) (uint2korr(head+6)+
602
((uint2korr(head+14) == 0xffff ?
603
uint4korr(head+47) : uint2korr(head+14))));
605
if ((n_length= uint4korr(head+55)))
607
/* Read extra data segment */
608
unsigned char *next_chunk, *buff_end;
609
if (!(next_chunk= buff= (unsigned char*) my_malloc(n_length, MYF(MY_WME))))
611
if (pread(file, buff, n_length, record_offset + share->reclength) == 0)
615
share->connect_string.length= uint2korr(buff);
616
if (!(share->connect_string.str= strmake_root(&share->mem_root,
617
(char*) next_chunk + 2,
618
share->connect_string.
623
next_chunk+= share->connect_string.length + 2;
624
buff_end= buff + n_length;
625
if (next_chunk + 2 < buff_end)
627
uint32_t str_db_type_length= uint2korr(next_chunk);
629
name.str= (char*) next_chunk + 2;
630
name.length= str_db_type_length;
632
plugin_ref tmp_plugin= ha_resolve_by_name(thd, &name);
633
if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, share->db_plugin))
635
if (legacy_db_type > DB_TYPE_UNKNOWN &&
636
legacy_db_type < DB_TYPE_FIRST_DYNAMIC &&
637
legacy_db_type != ha_legacy_type(
638
plugin_data(tmp_plugin, handlerton *)))
640
/* bad file, legacy_db_type did not match the name */
645
tmp_plugin is locked with a local lock.
646
we unlock the old value of share->db_plugin before
647
replacing it with a globally locked version of tmp_plugin
649
plugin_unlock(NULL, share->db_plugin);
650
share->db_plugin= my_plugin_lock(NULL, &tmp_plugin);
652
else if (!tmp_plugin)
654
/* purecov: begin inspected */
656
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
661
next_chunk+= str_db_type_length + 2;
663
if (share->mysql_version >= 50110)
665
/* New auto_partitioned indicator introduced in 5.1.11 */
668
if (forminfo[46] == (unsigned char)255)
670
//reading long table comment
671
if (next_chunk + 2 > buff_end)
676
share->comment.length = uint2korr(next_chunk);
677
if (! (share->comment.str= strmake_root(&share->mem_root,
678
(char*)next_chunk + 2, share->comment.length)))
683
next_chunk+= 2 + share->comment.length;
685
assert(next_chunk <= buff_end);
686
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM_CGE)
689
New frm format in mysql_version 5.2.5 (originally in
690
mysql-5.1.22-ndb-6.2.5)
691
New column properties added:
692
COLUMN_FORMAT DYNAMIC|FIXED and STORAGE DISK|MEMORY
693
TABLESPACE name is now stored in frm
695
if (next_chunk >= buff_end)
697
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM)
704
const uint32_t format_section_header_size= 8;
705
uint32_t format_section_len= uint2korr(next_chunk+0);
707
field_extra_info= next_chunk + format_section_header_size + 1;
708
next_chunk+= format_section_len;
711
assert (next_chunk <= buff_end);
712
if (next_chunk > buff_end)
717
share->key_block_size= uint2korr(head+62);
720
extra_rec_buf_length= uint2korr(head+59);
721
rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length);
722
share->rec_buff_length= rec_buff_length;
723
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
725
goto err; /* purecov: inspected */
726
share->default_values= record;
727
if (pread(file, record, (size_t) share->reclength, record_offset) == 0)
728
goto err; /* purecov: inspected */
730
my_seek(file,pos+288,MY_SEEK_SET,MYF(0));
732
share->fields= uint2korr(forminfo+258);
733
pos= uint2korr(forminfo+260); /* Length of all screens */
734
n_length= uint2korr(forminfo+268);
735
interval_count= uint2korr(forminfo+270);
736
interval_parts= uint2korr(forminfo+272);
737
int_length= uint2korr(forminfo+274);
738
share->null_fields= uint2korr(forminfo+282);
739
com_length= uint2korr(forminfo+284);
740
vcol_screen_length= uint2korr(forminfo+286);
742
share->stored_fields= share->fields;
743
if (forminfo[46] != (unsigned char)255)
745
share->comment.length= (int) (forminfo[46]);
746
share->comment.str= strmake_root(&share->mem_root, (char*) forminfo+47,
747
share->comment.length);
751
if (!(field_ptr = (Field **)
752
alloc_root(&share->mem_root,
753
(uint) ((share->fields+1)*sizeof(Field*)+
754
interval_count*sizeof(TYPELIB)+
755
(share->fields+interval_parts+
756
keys+3)*sizeof(char *)+
757
(n_length+int_length+com_length+
758
vcol_screen_length)))))
759
goto err; /* purecov: inspected */
761
share->field= field_ptr;
762
read_length=(uint) (share->fields * field_pack_length +
763
pos+ (uint) (n_length+int_length+com_length+
764
vcol_screen_length));
765
if (read_string(file,(unsigned char**) &disk_buff,read_length))
766
goto err; /* purecov: inspected */
767
strpos= disk_buff+pos;
769
share->intervals= (TYPELIB*) (field_ptr+share->fields+1);
770
interval_array= (const char **) (share->intervals+interval_count);
771
names= (char*) (interval_array+share->fields+interval_parts+keys+3);
773
share->intervals= 0; // For better debugging
774
memcpy(names, strpos+(share->fields*field_pack_length),
775
(uint) (n_length+int_length));
776
comment_pos= names+(n_length+int_length);
777
memcpy(comment_pos, disk_buff+read_length-com_length-vcol_screen_length,
779
vcol_screen_pos= names+(n_length+int_length+com_length);
780
memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length,
783
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
784
if (share->fieldnames.count != share->fields)
786
fix_type_pointers(&interval_array, share->intervals, interval_count,
790
/* Set ENUM and SET lengths */
792
for (interval= share->intervals;
793
interval < share->intervals + interval_count;
796
uint32_t count= (uint) (interval->count + 1) * sizeof(uint);
797
if (!(interval->type_lengths= (uint32_t *) alloc_root(&share->mem_root,
800
for (count= 0; count < interval->count; count++)
802
char *val= (char*) interval->type_names[count];
803
interval->type_lengths[count]= strlen(val);
805
interval->type_lengths[count]= 0;
810
fix_type_pointers(&interval_array, &share->keynames, 1, &keynames);
812
/* Allocate handler */
813
if (!(handler_file= get_new_handler(share, thd->mem_root,
817
record= share->default_values-1; /* Fieldstart = 1 */
818
if (share->null_field_first)
820
null_flags= null_pos= (unsigned char*) record+1;
821
null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
823
null_bytes below is only correct under the condition that
824
there are no bit fields. Correct values is set below after the
825
table struct is initialized
827
share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8;
830
use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
832
use_hash= !hash_init(&share->name_hash,
835
(hash_get_key) get_field_name,0,0);
837
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
839
uint32_t pack_flag, interval_nr, unireg_type, recpos, field_length;
840
uint32_t vcol_info_length=0;
841
enum_field_types field_type;
842
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
843
const CHARSET_INFO *charset= NULL;
845
virtual_column_info *vcol_info= NULL;
846
bool fld_is_stored= true;
848
if (field_extra_info)
850
char tmp= field_extra_info[i];
851
column_format= (enum column_format_type)
852
((tmp >> COLUMN_FORMAT_SHIFT) & COLUMN_FORMAT_MASK);
854
if (new_frm_ver >= 3)
856
/* new frm file in 4.1 */
857
field_length= uint2korr(strpos+3);
858
recpos= uint3korr(strpos+5);
859
pack_flag= uint2korr(strpos+8);
860
unireg_type= (uint) strpos[10];
861
interval_nr= (uint) strpos[12];
862
uint32_t comment_length=uint2korr(strpos+15);
863
field_type=(enum_field_types) (uint) strpos[13];
867
charset= &my_charset_bin;
868
else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
870
error= 5; // Unknown or unavailable charset
871
errarg= (int) strpos[14];
875
if (field_type == DRIZZLE_TYPE_VIRTUAL)
877
assert(interval_nr); // Expect non-null expression
879
The interval_id byte in the .frm file stores the length of the
880
expression statement for a virtual column.
882
vcol_info_length= interval_nr;
887
comment.str= (char*) "";
892
comment.str= (char*) comment_pos;
893
comment.length= comment_length;
894
comment_pos+= comment_length;
896
if (vcol_info_length)
899
Get virtual column data stored in the .frm file as follows:
900
byte 1 = 1 (always 1 to allow for future extensions)
902
byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
903
byte 4-... = virtual column expression (text data)
905
vcol_info= new virtual_column_info();
906
if ((uint)vcol_screen_pos[0] != 1)
911
field_type= (enum_field_types) (unsigned char) vcol_screen_pos[1];
912
fld_is_stored= (bool) (uint) vcol_screen_pos[2];
913
vcol_info->expr_str.str= (char *)memdup_root(&share->mem_root,
915
(uint)FRM_VCOL_HEADER_SIZE,
917
(uint)FRM_VCOL_HEADER_SIZE);
918
vcol_info->expr_str.length= vcol_info_length-(uint)FRM_VCOL_HEADER_SIZE;
919
vcol_screen_pos+= vcol_info_length;
925
field_length= (uint) strpos[3];
926
recpos= uint2korr(strpos+4),
927
pack_flag= uint2korr(strpos+6);
928
pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
929
unireg_type= (uint) strpos[8];
930
interval_nr= (uint) strpos[10];
933
field_type= (enum_field_types) f_packtype(pack_flag);
934
if (f_is_binary(pack_flag))
937
Try to choose the best 4.1 type:
938
- for 4.0 "CHAR(N) BINARY" or "VARCHAR(N) BINARY"
939
try to find a binary collation for character set.
940
- for other types (e.g. BLOB) just use my_charset_bin.
942
if (!f_is_blob(pack_flag))
944
// 3.23 or 4.0 string
945
if (!(charset= get_charset_by_csname(share->table_charset->csname,
946
MY_CS_BINSORT, MYF(0))))
947
charset= &my_charset_bin;
950
charset= &my_charset_bin;
953
charset= share->table_charset;
954
memset(&comment, 0, sizeof(comment));
957
if (interval_nr && charset->mbminlen > 1)
959
/* Unescape UCS2 intervals from HEX notation */
960
TYPELIB *interval= share->intervals + interval_nr - 1;
961
unhex_type2(interval);
964
*field_ptr= reg_field=
965
make_field(share, record+recpos,
966
(uint32_t) field_length,
967
null_pos, null_bit_pos,
971
(Field::utype) MTYP_TYPENR(unireg_type),
973
share->intervals+interval_nr-1 :
975
share->fieldnames.type_names[i]);
976
if (!reg_field) // Not supported field type
979
goto err; /* purecov: inspected */
982
reg_field->flags|= ((uint)column_format << COLUMN_FORMAT_FLAGS);
983
reg_field->field_index= i;
984
reg_field->comment=comment;
985
reg_field->vcol_info= vcol_info;
986
reg_field->is_stored= fld_is_stored;
987
if (!(reg_field->flags & NOT_NULL_FLAG))
989
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
992
if (f_no_default(pack_flag))
993
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
995
if (reg_field->unireg_check == Field::NEXT_NUMBER)
996
share->found_next_number_field= field_ptr;
997
if (share->timestamp_field == reg_field)
998
share->timestamp_field_offset= i;
1001
(void) my_hash_insert(&share->name_hash,
1002
(unsigned char*) field_ptr); // never fail
1003
if (!reg_field->is_stored)
1005
share->stored_fields--;
1006
if (share->stored_rec_length>=recpos)
1007
share->stored_rec_length= recpos-1;
1010
*field_ptr=0; // End marker
1011
/* Sanity checks: */
1012
assert(share->fields>=share->stored_fields);
1013
assert(share->reclength>=share->stored_rec_length);
1015
/* Fix key->name and key_part->field */
1018
uint32_t primary_key=(uint) (find_type((char*) primary_key_name,
1019
&share->keynames, 3) - 1);
1020
int64_t ha_option= handler_file->ha_table_flags();
1021
keyinfo= share->key_info;
1022
key_part= keyinfo->key_part;
1024
for (uint32_t key=0 ; key < share->keys ; key++,keyinfo++)
1026
uint32_t usable_parts= 0;
1027
keyinfo->name=(char*) share->keynames.type_names[key];
1029
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1032
If the UNIQUE key doesn't have NULL columns and is not a part key
1033
declare this as a primary key.
1036
for (i=0 ; i < keyinfo->key_parts ;i++)
1038
uint32_t fieldnr= key_part[i].fieldnr;
1040
share->field[fieldnr-1]->null_ptr ||
1041
share->field[fieldnr-1]->key_length() !=
1044
primary_key=MAX_KEY; // Can't be used
1050
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
1053
if (new_field_pack_flag <= 1)
1054
key_part->fieldnr= (uint16_t) find_field(share->field,
1055
share->default_values,
1056
(uint) key_part->offset,
1057
(uint) key_part->length);
1058
if (!key_part->fieldnr)
1060
error= 4; // Wrong file
1063
field= key_part->field= share->field[key_part->fieldnr-1];
1064
key_part->type= field->key_type();
1065
if (field->null_ptr)
1067
key_part->null_offset=(uint) ((unsigned char*) field->null_ptr -
1068
share->default_values);
1069
key_part->null_bit= field->null_bit;
1070
key_part->store_length+=HA_KEY_NULL_LENGTH;
1071
keyinfo->flags|=HA_NULL_PART_KEY;
1072
keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
1073
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
1075
if (field->type() == DRIZZLE_TYPE_BLOB ||
1076
field->real_type() == DRIZZLE_TYPE_VARCHAR)
1078
if (field->type() == DRIZZLE_TYPE_BLOB)
1079
key_part->key_part_flag|= HA_BLOB_PART;
1081
key_part->key_part_flag|= HA_VAR_LENGTH_PART;
1082
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
1083
key_part->store_length+=HA_KEY_BLOB_LENGTH;
1084
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
1086
if (i == 0 && key != primary_key)
1087
field->flags |= (((keyinfo->flags & HA_NOSAME) &&
1088
(keyinfo->key_parts == 1)) ?
1089
UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
1091
field->key_start.set_bit(key);
1092
if (field->key_length() == key_part->length &&
1093
!(field->flags & BLOB_FLAG))
1095
if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
1097
share->keys_for_keyread.set_bit(key);
1098
field->part_of_key.set_bit(key);
1099
field->part_of_key_not_clustered.set_bit(key);
1101
if (handler_file->index_flags(key, i, 1) & HA_READ_ORDER)
1102
field->part_of_sortkey.set_bit(key);
1104
if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
1106
usable_parts++; // For FILESORT
1107
field->flags|= PART_KEY_FLAG;
1108
if (key == primary_key)
1110
field->flags|= PRI_KEY_FLAG;
1112
If this field is part of the primary key and all keys contains
1113
the primary key, then we can use any key to find this column
1115
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
1117
field->part_of_key= share->keys_in_use;
1118
if (field->part_of_sortkey.is_set(key))
1119
field->part_of_sortkey= share->keys_in_use;
1122
if (field->key_length() != key_part->length)
1124
key_part->key_part_flag|= HA_PART_KEY_SEG;
1127
keyinfo->usable_key_parts= usable_parts; // Filesort
1129
set_if_bigger(share->max_key_length,keyinfo->key_length+
1130
keyinfo->key_parts);
1131
share->total_key_length+= keyinfo->key_length;
1133
MERGE tables do not have unique indexes. But every key could be
1134
an unique index on the underlying MyISAM table. (Bug #10400)
1136
if ((keyinfo->flags & HA_NOSAME) ||
1137
(ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
1138
set_if_bigger(share->max_unique_length,keyinfo->key_length);
1140
if (primary_key < MAX_KEY &&
1141
(share->keys_in_use.is_set(primary_key)))
1143
share->primary_key= primary_key;
1145
If we are using an integer as the primary key then allow the user to
1146
refer to it as '_rowid'
1148
if (share->key_info[primary_key].key_parts == 1)
1150
Field *field= share->key_info[primary_key].key_part[0].field;
1151
if (field && field->result_type() == INT_RESULT)
1153
/* note that fieldnr here (and rowid_field_offset) starts from 1 */
1154
share->rowid_field_offset= (share->key_info[primary_key].key_part[0].
1160
share->primary_key = MAX_KEY; // we do not have a primary key
1163
share->primary_key= MAX_KEY;
1167
if (new_field_pack_flag <= 1)
1169
/* Old file format with default as not null */
1170
uint32_t null_length= (share->null_fields+7)/8;
1171
memset(share->default_values + (null_flags - (unsigned char*) record),
1175
if (share->found_next_number_field)
1177
reg_field= *share->found_next_number_field;
1178
if ((int) (share->next_number_index= (uint)
1179
find_ref_key(share->key_info, share->keys,
1180
share->default_values, reg_field,
1181
&share->next_number_key_offset,
1182
&share->next_number_keypart)) < 0)
1184
/* Wrong field definition */
1189
reg_field->flags |= AUTO_INCREMENT_FLAG;
1192
if (share->blob_fields)
1197
/* Store offsets to blob fields to find them fast */
1198
if (!(share->blob_field= save=
1199
(uint*) alloc_root(&share->mem_root,
1200
(uint) (share->blob_fields* sizeof(uint)))))
1202
for (k=0, ptr= share->field ; *ptr ; ptr++, k++)
1204
if ((*ptr)->flags & BLOB_FLAG)
1210
the correct null_bytes can now be set, since bitfields have been taken
1213
share->null_bytes= (null_pos - (unsigned char*) null_flags +
1214
(null_bit_pos + 7) / 8);
1215
share->last_null_bit_pos= null_bit_pos;
1217
share->db_low_byte_first= handler_file->low_byte_first();
1218
share->column_bitmap_size= bitmap_buffer_size(share->fields);
1220
if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1221
share->column_bitmap_size)))
1223
bitmap_init(&share->all_set, bitmaps, share->fields, false);
1224
bitmap_set_all(&share->all_set);
1226
delete handler_file;
1234
share->error= error;
1235
share->open_errno= my_errno;
1236
share->errarg= errarg;
1239
delete handler_file;
1240
hash_free(&share->name_hash);
1242
open_table_error(share, error, share->open_errno, errarg);
1244
} /* open_binary_frm */
1248
Clear flag GET_FIXED_FIELDS_FLAG in all fields of the table.
1249
This routine is used for error handling purposes.
1253
table Table object for which virtual columns are set-up
1258
static void clear_field_flag(Table *table)
1262
for (ptr= table->field; *ptr; ptr++)
1263
(*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
1267
The function uses the feature in fix_fields where the flag
1268
GET_FIXED_FIELDS_FLAG is set for all fields in the item tree.
1269
This field must always be reset before returning from the function
1270
since it is used for other purposes as well.
1273
fix_fields_vcol_func()
1274
thd The thread object
1275
func_item The item tree reference of the virtual columnfunction
1276
table The table object
1277
field_name The name of the processed field
1280
true An error occurred, something was wrong with the
1282
false Ok, a partition field array was created
1285
bool fix_fields_vcol_func(THD *thd,
1288
const char *field_name)
1290
uint dir_length, home_dir_length;
1293
TableList *save_table_list, *save_first_table, *save_last_table;
1295
Name_resolution_context *context;
1296
const char *save_where;
1298
char db_name_string[FN_REFLEN];
1299
bool save_use_only_table_context;
1300
Field **ptr, *field;
1301
enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
1305
Set-up the TABLE_LIST object to be a list with a single table
1306
Set the object to zero to create NULL pointers and set alias
1307
and real name to table name and get database name from file name.
1310
bzero((void*)&tables, sizeof(TableList));
1311
tables.alias= tables.table_name= (char*) table->s->table_name.str;
1312
tables.table= table;
1313
tables.next_local= NULL;
1314
tables.next_name_resolution_table= NULL;
1315
memcpy(db_name_string,
1316
table->s->normalized_path.str,
1317
table->s->normalized_path.length);
1318
dir_length= dirname_length(db_name_string);
1319
db_name_string[dir_length - 1]= 0;
1320
home_dir_length= dirname_length(db_name_string);
1321
db_name= &db_name_string[home_dir_length];
1324
thd->mark_used_columns= MARK_COLUMNS_NONE;
1326
context= thd->lex->current_context();
1327
table->map= 1; //To ensure correct calculation of const item
1328
table->get_fields_in_item_tree= true;
1329
save_table_list= context->table_list;
1330
save_first_table= context->first_name_resolution_table;
1331
save_last_table= context->last_name_resolution_table;
1332
context->table_list= &tables;
1333
context->first_name_resolution_table= &tables;
1334
context->last_name_resolution_table= NULL;
1335
func_expr->walk(&Item::change_context_processor, 0, (unsigned char*) context);
1336
save_where= thd->where;
1337
thd->where= "virtual column function";
1339
/* Save the context before fixing the fields*/
1340
save_use_only_table_context= thd->lex->use_only_table_context;
1341
thd->lex->use_only_table_context= true;
1342
/* Fix fields referenced to by the virtual column function */
1343
error= func_expr->fix_fields(thd, (Item**)0);
1344
/* Restore the original context*/
1345
thd->lex->use_only_table_context= save_use_only_table_context;
1346
context->table_list= save_table_list;
1347
context->first_name_resolution_table= save_first_table;
1348
context->last_name_resolution_table= save_last_table;
1350
if (unlikely(error))
1352
clear_field_flag(table);
1355
thd->where= save_where;
1357
Walk through the Item tree checking if all items are valid
1358
to be part of the virtual column
1360
error= func_expr->walk(&Item::check_vcol_func_processor, 0, NULL);
1363
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
1364
clear_field_flag(table);
1367
if (unlikely(func_expr->const_item()))
1369
my_error(ER_CONST_EXPR_IN_VCOL, MYF(0));
1370
clear_field_flag(table);
1373
/* Ensure that this virtual column is not based on another virtual field. */
1375
while ((field= *(ptr++)))
1377
if ((field->flags & GET_FIXED_FIELDS_FLAG) &&
1380
my_error(ER_VCOL_BASED_ON_VCOL, MYF(0));
1381
clear_field_flag(table);
1386
Cleanup the fields marked with flag GET_FIXED_FIELDS_FLAG
1387
when calling fix_fields.
1389
clear_field_flag(table);
1393
table->get_fields_in_item_tree= false;
1394
thd->mark_used_columns= save_mark_used_columns;
1395
table->map= 0; //Restore old value
1400
Unpack the definition of a virtual column
1403
unpack_vcol_info_from_frm()
1405
table Table with the checked field
1406
field Pointer to Field object
1407
open_mode Open table mode needed to determine
1408
which errors need to be generated in a failure
1409
error_reported updated flag for the caller that no other error
1410
messages are to be generated.
1416
bool unpack_vcol_info_from_frm(THD *thd,
1419
LEX_STRING *vcol_expr,
1420
open_table_mode open_mode,
1421
bool *error_reported)
1426
Step 1: Construct a statement for the parser.
1427
The parsed string needs to take the following format:
1428
"PARSE_VCOL_EXPR (<expr_string_from_frm>)"
1430
char *vcol_expr_str;
1433
if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
1435
parse_vcol_keyword.length + 3)))
1439
memcpy(vcol_expr_str,
1440
(char*) parse_vcol_keyword.str,
1441
parse_vcol_keyword.length);
1442
str_len= parse_vcol_keyword.length;
1443
memcpy(vcol_expr_str + str_len, "(", 1);
1445
memcpy(vcol_expr_str + str_len,
1446
(char*) vcol_expr->str,
1448
str_len+= vcol_expr->length;
1449
memcpy(vcol_expr_str + str_len, ")", 1);
1451
memcpy(vcol_expr_str + str_len, "\0", 1);
1453
Lex_input_stream lip(thd, vcol_expr_str, str_len);
1456
Step 2: Setup thd for parsing.
1457
1) make Item objects be created in the memory allocated for the Table
1458
object (not TABLE_SHARE)
1459
2) ensure that created Item's are not put on to thd->free_list
1460
(which is associated with the parsed statement and hence cleared after
1462
3) setup a flag in the LEX structure to allow "PARSE_VCOL_EXPR"
1463
to be parsed as a SQL command.
1465
MEM_ROOT **root_ptr, *old_root;
1466
Item *backup_free_list= thd->free_list;
1467
root_ptr= (MEM_ROOT **)pthread_getspecific(THR_MALLOC);
1468
old_root= *root_ptr;
1469
*root_ptr= &table->mem_root;
1470
thd->free_list= NULL;
1471
thd->lex->parse_vcol_expr= true;
1474
Step 3: Use the parser to build an Item object from.
1476
if (parse_sql(thd, &lip))
1480
/* From now on use vcol_info generated by the parser. */
1481
field->vcol_info= thd->lex->vcol_info;
1483
/* Validate the Item tree. */
1484
if (fix_fields_vcol_func(thd,
1485
field->vcol_info->expr_item,
1489
if (open_mode == OTM_CREATE)
1492
During CREATE/ALTER TABLE it is ok to receive errors here.
1493
It is not ok if it happens during the opening of an frm
1494
file as part of a normal query.
1496
*error_reported= true;
1498
field->vcol_info= NULL;
1501
field->vcol_info->item_free_list= thd->free_list;
1502
thd->free_list= backup_free_list;
1503
*root_ptr= old_root;
1508
thd->lex->parse_vcol_expr= false;
1510
*root_ptr= old_root;
1511
thd->free_list= backup_free_list;
1517
Open a table based on a TABLE_SHARE
1520
open_table_from_share()
1522
share Table definition
1523
alias Alias for table
1524
db_stat open flags (for example HA_OPEN_KEYFILE|
1525
HA_OPEN_RNDFILE..) can be 0 (example in
1527
prgflag READ_ALL etc..
1528
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
1529
outparam result table
1530
open_mode One of OTM_OPEN|OTM_CREATE|OTM_ALTER
1531
if OTM_CREATE some errors are ignore
1532
if OTM_ALTER HA_OPEN is not called
1536
1 Error (see open_table_error)
1537
2 Error (see open_table_error)
1538
3 Wrong data in .frm file
1539
4 Error (see open_table_error)
1540
5 Error (see open_table_error: charset unavailable)
1541
7 Table definition has changed in engine
1544
int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
1545
uint32_t db_stat, uint32_t prgflag, uint32_t ha_open_flags,
1546
Table *outparam, open_table_mode open_mode)
1549
uint32_t records, i, bitmap_size;
1550
bool error_reported= false;
1551
unsigned char *record, *bitmaps;
1552
Field **field_ptr, **vfield_ptr;
1554
/* Parsing of partitioning information from .frm needs thd->lex set up. */
1555
assert(thd->lex->is_lex_started);
1558
memset(outparam, 0, sizeof(*outparam));
1559
outparam->in_use= thd;
1561
outparam->db_stat= db_stat;
1562
outparam->write_row_record= NULL;
1564
init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
1566
if (!(outparam->alias= my_strdup(alias, MYF(MY_WME))))
1568
outparam->quick_keys.init();
1569
outparam->covering_keys.init();
1570
outparam->keys_in_use_for_query.init();
1572
/* Allocate handler */
1574
if (!(prgflag & OPEN_FRM_FILE_ONLY))
1576
if (!(outparam->file= get_new_handler(share, &outparam->mem_root,
1586
outparam->reginfo.lock_type= TL_UNLOCK;
1587
outparam->current_lock= F_UNLCK;
1589
if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
1591
if (prgflag & (READ_ALL+EXTRA_RECORD))
1594
if (!(record= (unsigned char*) alloc_root(&outparam->mem_root,
1595
share->rec_buff_length * records)))
1596
goto err; /* purecov: inspected */
1600
/* We are probably in hard repair, and the buffers should not be used */
1601
outparam->record[0]= outparam->record[1]= share->default_values;
1605
outparam->record[0]= record;
1607
outparam->record[1]= record+ share->rec_buff_length;
1609
outparam->record[1]= outparam->record[0]; // Safety
1614
We need this because when we read var-length rows, we are not updating
1615
bytes after end of varchar
1619
memcpy(outparam->record[0], share->default_values, share->rec_buff_length);
1620
memcpy(outparam->record[1], share->default_values, share->null_bytes);
1622
memcpy(outparam->record[1], share->default_values,
1623
share->rec_buff_length);
1627
if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root,
1628
(uint) ((share->fields+1)*
1630
goto err; /* purecov: inspected */
1632
outparam->field= field_ptr;
1634
record= (unsigned char*) outparam->record[0]-1; /* Fieldstart = 1 */
1635
if (share->null_field_first)
1636
outparam->null_flags= (unsigned char*) record+1;
1638
outparam->null_flags= (unsigned char*) (record+ 1+ share->reclength -
1641
/* Setup copy of fields from share, but use the right alias and record */
1642
for (i=0 ; i < share->fields; i++, field_ptr++)
1644
if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam)))
1647
(*field_ptr)= 0; // End marker
1649
if (share->found_next_number_field)
1650
outparam->found_next_number_field=
1651
outparam->field[(uint) (share->found_next_number_field - share->field)];
1652
if (share->timestamp_field)
1653
outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
1656
/* Fix key->name and key_part->field */
1657
if (share->key_parts)
1659
KEY *key_info, *key_info_end;
1660
KEY_PART_INFO *key_part;
1662
n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO);
1663
if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length)))
1665
outparam->key_info= key_info;
1666
key_part= (reinterpret_cast<KEY_PART_INFO*> (key_info+share->keys));
1668
memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
1669
memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) *
1672
for (key_info_end= key_info + share->keys ;
1673
key_info < key_info_end ;
1676
KEY_PART_INFO *key_part_end;
1678
key_info->table= outparam;
1679
key_info->key_part= key_part;
1681
for (key_part_end= key_part+ key_info->key_parts ;
1682
key_part < key_part_end ;
1685
Field *field= key_part->field= outparam->field[key_part->fieldnr-1];
1687
if (field->key_length() != key_part->length &&
1688
!(field->flags & BLOB_FLAG))
1691
We are using only a prefix of the column as a key:
1692
Create a new field for the key part that matches the index
1694
field= key_part->field=field->new_field(&outparam->mem_root,
1696
field->field_length= key_part->length;
1703
Process virtual columns, if any.
1705
if (not (vfield_ptr = (Field **) alloc_root(&outparam->mem_root,
1706
(uint) ((share->vfields+1)*
1710
outparam->vfield= vfield_ptr;
1712
for (field_ptr= outparam->field; *field_ptr; field_ptr++)
1714
if ((*field_ptr)->vcol_info)
1716
if (unpack_vcol_info_from_frm(thd,
1719
&(*field_ptr)->vcol_info->expr_str,
1723
error= 4; // in case no error is reported
1726
*(vfield_ptr++)= *field_ptr;
1729
*vfield_ptr= NULL; // End marker
1730
/* Check virtual columns against table's storage engine. */
1731
if ((share->vfields && outparam->file) &&
1732
(not outparam->file->check_if_supported_virtual_columns()))
1734
my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN,
1736
"Specified storage engine");
1737
error_reported= true;
1741
/* Allocate bitmaps */
1743
bitmap_size= share->column_bitmap_size;
1744
if (!(bitmaps= (unsigned char*) alloc_root(&outparam->mem_root, bitmap_size*3)))
1746
bitmap_init(&outparam->def_read_set,
1747
(my_bitmap_map*) bitmaps, share->fields, false);
1748
bitmap_init(&outparam->def_write_set,
1749
(my_bitmap_map*) (bitmaps+bitmap_size), share->fields, false);
1750
bitmap_init(&outparam->tmp_set,
1751
(my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, false);
1752
outparam->default_column_bitmaps();
1754
/* The table struct is now initialized; Open the table */
1756
if (db_stat && open_mode != OTM_ALTER)
1759
if ((ha_err= (outparam->file->
1760
ha_open(outparam, share->normalized_path.str,
1761
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
1762
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
1763
(db_stat & HA_WAIT_IF_LOCKED) ? HA_OPEN_WAIT_IF_LOCKED :
1764
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
1765
HA_OPEN_ABORT_IF_LOCKED :
1766
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
1768
/* Set a flag if the table is crashed and it can be auto. repaired */
1769
share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
1770
outparam->file->auto_repair() &&
1771
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
1775
case HA_ERR_NO_SUCH_TABLE:
1777
The table did not exists in storage engine, use same error message
1778
as if the .frm file didn't exist
1785
Too many files opened, use same error message as if the .frm
1792
outparam->file->print_error(ha_err, MYF(0));
1793
error_reported= true;
1794
if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
1798
goto err; /* purecov: inspected */
1802
#if defined(HAVE_purify)
1803
memset(bitmaps, 0, bitmap_size*3);
1806
outparam->no_replicate= outparam->file;
1807
thd->status_var.opened_tables++;
1812
if (!error_reported && !(prgflag & DONT_GIVE_ERROR))
1813
open_table_error(share, error, my_errno, 0);
1814
delete outparam->file;
1815
outparam->file= 0; // For easier error checking
1816
outparam->db_stat=0;
1817
free_root(&outparam->mem_root, MYF(0)); // Safe to call on zeroed root
1818
free((char*) outparam->alias);
1824
Free information allocated by openfrm
1828
table Table object to free
1829
free_share Is 1 if we also want to free table_share
1832
int closefrm(register Table *table, bool free_share)
1837
error=table->file->close();
1838
free((char*) table->alias);
1842
for (Field **ptr=table->field ; *ptr ; ptr++)
1847
table->file= 0; /* For easier errorchecking */
1850
if (table->s->tmp_table == NO_TMP_TABLE)
1851
release_table_share(table->s, RELEASE_NORMAL);
1853
free_table_share(table->s);
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);
1855
free_root(&table->mem_root, MYF(0));
198
1860
/* Deallocate temporary blob storage */
200
void free_blobs(Table *table)
1862
void free_blobs(register Table *table)
202
1864
uint32_t *ptr, *end;
203
1865
for (ptr= table->getBlobField(), end=ptr + table->sizeBlobFields();
207
((Field_blob*) table->getField(*ptr))->free();
212
TYPELIB *typelib(memory::Root *mem_root, List<String> &strings)
214
TYPELIB *result= (TYPELIB*) mem_root->alloc_root(sizeof(TYPELIB));
1868
((Field_blob*) table->field[*ptr])->free();
1872
/* Find where a form starts */
1873
/* if formname is NULL then only formnames is read */
1875
ulong get_form_pos(File file, unsigned char *head, TYPELIB *save_names)
1877
uint32_t a_length,names,length;
1878
unsigned char *pos,*buf;
1881
names=uint2korr(head+8);
1882
a_length=(names+2)*sizeof(char *); /* Room for two extra */
1887
save_names->type_names=0; /* Clear if error */
1891
length=uint2korr(head+4);
1892
my_seek(file,64L,MY_SEEK_SET,MYF(0));
1893
if (!(buf= (unsigned char*) my_malloc((size_t) length+a_length+names*4,
1895
my_read(file, buf+a_length, (size_t) (length+names*4),
1897
{ /* purecov: inspected */
1900
return(0L); /* purecov: inspected */
1902
pos= buf+a_length+length;
1903
ret_value=uint4korr(pos);
1908
free((unsigned char*) buf);
1911
memset(save_names, 0, sizeof(save_names));
1915
str=(char *) (buf+a_length);
1916
fix_type_pointers((const char ***) &buf,save_names,1,&str);
1923
Read string from a file with malloc
1926
We add an \0 at end of the read string to make reading of C strings easier
1929
int read_string(File file, unsigned char**to, size_t length)
1934
if (!(*to= (unsigned char*) my_malloc(length+1,MYF(MY_WME))) ||
1935
my_read(file, *to, length,MYF(MY_NABP)))
1940
return(1); /* purecov: inspected */
1942
*((char*) *to+length)= '\0';
1947
/* Add a new form to a form file */
1949
ulong make_new_entry(File file, unsigned char *fileinfo, TYPELIB *formnames,
1950
const char *newname)
1952
uint32_t i,bufflength,maxlength,n_length,length,names;
1953
ulong endpos,newpos;
1954
unsigned char buff[IO_SIZE];
1957
length=(uint) strlen(newname)+1;
1958
n_length=uint2korr(fileinfo+4);
1959
maxlength=uint2korr(fileinfo+6);
1960
names=uint2korr(fileinfo+8);
1961
newpos=uint4korr(fileinfo+10);
1963
if (64+length+n_length+(names+1)*4 > maxlength)
1966
int4store(fileinfo+10,newpos);
1967
endpos=(ulong) my_seek(file,0L,MY_SEEK_END,MYF(0));/* Copy from file-end */
1968
bufflength= (uint) (endpos & (IO_SIZE-1)); /* IO_SIZE is a power of 2 */
1970
while (endpos > maxlength)
1972
my_seek(file,(ulong) (endpos-bufflength),MY_SEEK_SET,MYF(0));
1973
if (my_read(file, buff, bufflength, MYF(MY_NABP+MY_WME)))
1975
my_seek(file,(ulong) (endpos-bufflength+IO_SIZE),MY_SEEK_SET,
1977
if ((my_write(file, buff,bufflength,MYF(MY_NABP+MY_WME))))
1979
endpos-=bufflength; bufflength=IO_SIZE;
1981
memset(buff, 0, IO_SIZE); /* Null new block */
1982
my_seek(file,(ulong) maxlength,MY_SEEK_SET,MYF(0));
1983
if (my_write(file,buff,bufflength,MYF(MY_NABP+MY_WME)))
1985
maxlength+=IO_SIZE; /* Fix old ref */
1986
int2store(fileinfo+6,maxlength);
1987
for (i=names, pos= (unsigned char*) *formnames->type_names+n_length-1; i-- ;
1990
endpos=uint4korr(pos)+IO_SIZE;
1991
int4store(pos,endpos);
1998
strxmov((char*) buff,"/",newname,"/",NULL);
2001
strxmov((char*) buff,newname,"/",NULL); /* purecov: inspected */
2002
my_seek(file,63L+(ulong) n_length,MY_SEEK_SET,MYF(0));
2003
if (my_write(file, buff, (size_t) length+1,MYF(MY_NABP+MY_WME)) ||
2004
(names && my_write(file,(unsigned char*) (*formnames->type_names+n_length-1),
2005
names*4, MYF(MY_NABP+MY_WME))) ||
2006
my_write(file, fileinfo+10, 4,MYF(MY_NABP+MY_WME)))
2007
return(0L); /* purecov: inspected */
2009
int2store(fileinfo+8,names+1);
2010
int2store(fileinfo+4,n_length+length);
2011
assert(ftruncate(file, newpos)==0);/* Append file with '\0' */
2013
} /* make_new_entry */
2016
/* error message when opening a form file */
2018
void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg)
2021
char buff[FN_REFLEN];
2022
myf errortype= ME_ERROR+ME_WAITTANG;
2027
if (db_errno == ENOENT)
2028
my_error(ER_NO_SUCH_TABLE, MYF(0), share->db.str, share->table_name.str);
2031
strxmov(buff, share->normalized_path.str, reg_ext, NULL);
2032
my_error((db_errno == EMFILE) ? ER_CANT_OPEN_FILE : ER_FILE_NOT_FOUND,
2033
errortype, buff, db_errno);
2039
const char *datext= "";
2041
if (share->db_type() != NULL)
2043
if ((file= get_new_handler(share, current_thd->mem_root,
2046
if (!(datext= *file->bas_ext()))
2050
err_no= (db_errno == ENOENT) ? ER_FILE_NOT_FOUND : (db_errno == EAGAIN) ?
2051
ER_FILE_USED : ER_CANT_OPEN_FILE;
2052
strxmov(buff, share->normalized_path.str, datext, NULL);
2053
my_error(err_no,errortype, buff, db_errno);
2059
const char *csname= get_charset_name((uint) errarg);
2061
if (!csname || csname[0] =='?')
2063
snprintf(tmp, sizeof(tmp), "#%d", errarg);
2066
my_printf_error(ER_UNKNOWN_COLLATION,
2067
_("Unknown collation '%s' in table '%-.64s' definition"),
2068
MYF(0), csname, share->table_name.str);
2072
strxmov(buff, share->normalized_path.str, reg_ext, NULL);
2073
my_printf_error(ER_NOT_FORM_FILE,
2074
_("Table '%-.64s' was created with a different version "
2075
"of MySQL and cannot be read"),
2080
default: /* Better wrong error than none */
2082
strxmov(buff, share->normalized_path.str, reg_ext, NULL);
2083
my_error(ER_NOT_FORM_FILE, errortype, buff, 0);
2087
} /* open_table_error */
2091
** fix a str_type to a array type
2092
** typeparts separated with some char. differents types are separated
2097
fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint32_t types,
2100
char *type_name, *ptr;
2106
point_to_type->name=0;
2107
point_to_type->type_names= *array;
2109
if ((chr= *ptr)) /* Test if empty type */
2111
while ((type_name=strchr(ptr+1,chr)) != NULL)
2113
*((*array)++) = ptr+1;
2114
*type_name= '\0'; /* End string */
2117
ptr+=2; /* Skip end mark and last 0 */
2121
point_to_type->count= (uint) (*array - point_to_type->type_names);
2123
*((*array)++)= NULL; /* End of type */
2125
*names=ptr; /* Update end */
2127
} /* fix_type_pointers */
2130
TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
2132
TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
217
result->count= strings.elements;
219
uint32_t nbytes= (sizeof(char*) + sizeof(uint32_t)) * (result->count + 1);
221
if (!(result->type_names= (const char**) mem_root->alloc_root(nbytes)))
2135
result->count=strings.elements;
2137
uint32_t nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
2138
if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
224
2140
result->type_lengths= (uint*) (result->type_names + result->count + 1);
226
List<String>::iterator it(strings.begin());
2141
List_iterator<String> it(strings);
228
for (uint32_t i= 0; (tmp= it++); i++)
2143
for (uint32_t i=0; (tmp=it++) ; i++)
230
2145
result->type_names[i]= tmp->ptr();
231
2146
result->type_lengths[i]= tmp->length();
234
result->type_names[result->count]= 0; // End marker
2148
result->type_names[result->count]= 0; // End marker
235
2149
result->type_lengths[result->count]= 0;
2155
Search after a field with given start & length
2156
If an exact field isn't found, return longest field with starts
2160
This is needed because in some .frm fields 'fieldnr' was saved wrong
2167
static uint32_t find_field(Field **fields, unsigned char *record, uint32_t start, uint32_t length)
2173
for (field= fields, i=1 ; *field ; i++,field++)
2175
if ((*field)->offset(record) == start)
2177
if ((*field)->key_length() == length)
2179
if (!pos || fields[pos-1]->pack_length() <
2180
(*field)->pack_length())
240
2188
/* Check that the integer is in the internal */
242
int set_zone(int nr, int min_zone, int max_zone)
2190
int set_zone(register int nr, int min_zone, int max_zone)
244
2192
if (nr<=min_zone)
245
2193
return (min_zone);
1351
4615
((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
1352
4616
(ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
1353
4617
(ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
4618
0 : FIELDFLAG_BINARY;
1358
if (session->is_fatal_error) // If end of memory
1360
table->getMutableShare()->db_record_offset= 1;
1361
if (table->getShare()->db_type() == myisam_engine)
4622
if (thd->is_fatal_error) // If end of memory
4623
goto err; /* purecov: inspected */
4624
share->db_record_offset= 1;
4625
if (share->db_type() == myisam_hton)
1363
4627
if (table->create_myisam_tmp_table(param->keyinfo, param->start_recinfo,
1364
4628
¶m->recinfo, select_options))
1367
assert(table->in_use);
1368
4631
if (table->open_tmp_table())
1371
session->mem_root= mem_root_save;
4634
thd->mem_root= mem_root_save;
1376
session->mem_root= mem_root_save;
4639
thd->mem_root= mem_root_save;
4640
table->free_tmp_table(thd); /* purecov: inspected */
4641
if (temp_pool_slot != MY_BIT_NONE)
4642
bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
4643
return(NULL); /* purecov: inspected */
1382
4646
/****************************************************************************/
1384
void Table::column_bitmaps_set(boost::dynamic_bitset<>& read_set_arg,
1385
boost::dynamic_bitset<>& write_set_arg)
1387
read_set= &read_set_arg;
1388
write_set= &write_set_arg;
1392
const boost::dynamic_bitset<> Table::use_all_columns(boost::dynamic_bitset<>& in_map)
1394
const boost::dynamic_bitset<> old= in_map;
1395
in_map= getShare()->all_set;
4649
Create a reduced Table object with properly set up Field list from a
4650
list of field definitions.
4652
The created table doesn't have a table handler associated with
4653
it, has no keys, no group/distinct, no copy_funcs array.
4654
The sole purpose of this Table object is to use the power of Field
4655
class to read/write data to/from table->record[0]. Then one can store
4656
the record in any container (RB tree, hash, etc).
4657
The table is created in THD mem_root, so are the table's fields.
4658
Consequently, if you don't BLOB fields, you don't need to free it.
4660
@param thd connection handle
4661
@param field_list list of column definitions
4664
0 if out of memory, Table object in case of success
4667
Table *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
4669
uint32_t field_count= field_list.elements;
4670
uint32_t blob_count= 0;
4672
Create_field *cdef; /* column definition */
4673
uint32_t record_length= 0;
4674
uint32_t null_count= 0; /* number of columns which may be null */
4675
uint32_t null_pack_length; /* NULL representation array length */
4676
uint32_t *blob_field;
4677
unsigned char *bitmaps;
4681
if (!multi_alloc_root(thd->mem_root,
4682
&table, sizeof(*table),
4683
&share, sizeof(*share),
4684
&field, (field_count + 1) * sizeof(Field*),
4685
&blob_field, (field_count+1) *sizeof(uint),
4686
&bitmaps, bitmap_buffer_size(field_count)*2,
4690
memset(table, 0, sizeof(*table));
4691
memset(share, 0, sizeof(*share));
4692
table->field= field;
4694
share->blob_field= blob_field;
4695
share->fields= field_count;
4696
share->blob_ptr_size= portable_sizeof_char_ptr;
4697
table->setup_tmp_table_column_bitmaps(bitmaps);
4699
/* Create all fields and calculate the total length of record */
4700
List_iterator_fast<Create_field> it(field_list);
4701
while ((cdef= it++))
4703
*field= make_field(share, 0, cdef->length,
4704
(unsigned char*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
4705
f_maybe_null(cdef->pack_flag) ? 1 : 0,
4706
cdef->pack_flag, cdef->sql_type, cdef->charset,
4708
cdef->interval, cdef->field_name);
4711
(*field)->init(table);
4712
record_length+= (*field)->pack_length();
4713
if (! ((*field)->flags & NOT_NULL_FLAG))
4716
if ((*field)->flags & BLOB_FLAG)
4717
share->blob_field[blob_count++]= (uint) (field - table->field);
4721
*field= NULL; /* mark the end of the list */
4722
share->blob_field[blob_count]= 0; /* mark the end of the list */
4723
share->blob_fields= blob_count;
4725
null_pack_length= (null_count + 7)/8;
4726
share->reclength= record_length + null_pack_length;
4727
share->rec_buff_length= ALIGN_SIZE(share->reclength + 1);
4728
table->record[0]= (unsigned char*) thd->alloc(share->rec_buff_length);
4729
if (!table->record[0])
4732
if (null_pack_length)
4734
table->null_flags= (unsigned char*) table->record[0];
4735
share->null_fields= null_count;
4736
share->null_bytes= null_pack_length;
4739
table->in_use= thd; /* field->reset() may access table->in_use */
4741
/* Set up field pointers */
4742
unsigned char *null_pos= table->record[0];
4743
unsigned char *field_pos= null_pos + share->null_bytes;
4744
uint32_t null_bit= 1;
4746
for (field= table->field; *field; ++field)
4748
Field *cur_field= *field;
4749
if ((cur_field->flags & NOT_NULL_FLAG))
4750
cur_field->move_field(field_pos);
4753
cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
4755
if (null_bit == (1 << 8))
4763
field_pos+= cur_field->pack_length();
4768
for (field= table->field; *field; ++field)
4769
delete *field; /* just invokes field destructor */
4774
bool Table::open_tmp_table()
4777
if ((error=file->ha_open(this, s->table_name.str,O_RDWR,
4778
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
4780
file->print_error(error,MYF(0)); /* purecov: inspected */
4784
(void) file->extra(HA_EXTRA_QUICK); /* Faster */
4790
Create MyISAM temporary table
4793
create_myisam_tmp_table()
4794
keyinfo Description of the index (there is always one index)
4795
start_recinfo MyISAM's column descriptions
4796
recinfo INOUT End of MyISAM's column descriptions
4800
Create a MyISAM temporary table according to passed description. The is
4801
assumed to have one unique index or constraint.
4803
The passed array or MI_COLUMNDEF structures must have this form:
4805
1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
4806
when there are many nullable columns)
4808
3. One free MI_COLUMNDEF element (*recinfo points here)
4810
This function may use the free element to create hash column for unique
4818
bool Table::create_myisam_tmp_table(KEY *keyinfo,
4819
MI_COLUMNDEF *start_recinfo,
4820
MI_COLUMNDEF **recinfo,
4825
MI_UNIQUEDEF uniquedef;
4826
TABLE_SHARE *share= s;
4829
{ // Get keys for ni_create
4830
bool using_unique_constraint=0;
4831
HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&this->mem_root,
4832
sizeof(*seg) * keyinfo->key_parts);
4836
memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
4837
if (keyinfo->key_length >= file->max_key_length() ||
4838
keyinfo->key_parts > file->max_key_parts() ||
4841
/* Can't create a key; Make a unique constraint instead of a key */
4844
using_unique_constraint=1;
4845
memset(&uniquedef, 0, sizeof(uniquedef));
4846
uniquedef.keysegs=keyinfo->key_parts;
4848
uniquedef.null_are_equal=1;
4850
/* Create extra column for hash value */
4851
memset(*recinfo, 0, sizeof(**recinfo));
4852
(*recinfo)->type= FIELD_CHECK;
4853
(*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
4855
share->reclength+=MI_UNIQUE_HASH_LENGTH;
4859
/* Create an unique key */
4860
memset(&keydef, 0, sizeof(keydef));
4861
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
4862
keydef.keysegs= keyinfo->key_parts;
4865
for (uint32_t i=0; i < keyinfo->key_parts ; i++,seg++)
4867
Field *field=keyinfo->key_part[i].field;
4869
seg->language= field->charset()->number;
4870
seg->length= keyinfo->key_part[i].length;
4871
seg->start= keyinfo->key_part[i].offset;
4872
if (field->flags & BLOB_FLAG)
4875
((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
4876
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
4877
seg->bit_start= (uint8_t)(field->pack_length() - share->blob_ptr_size);
4878
seg->flag= HA_BLOB_PART;
4879
seg->length=0; // Whole blob in unique constraint
4883
seg->type= keyinfo->key_part[i].type;
4885
if (!(field->flags & NOT_NULL_FLAG))
4887
seg->null_bit= field->null_bit;
4888
seg->null_pos= (uint) (field->null_ptr - (unsigned char*) record[0]);
4890
We are using a GROUP BY on something that contains NULL
4891
In this case we have to tell MyISAM that two NULL should
4892
on INSERT be regarded at the same value
4894
if (!using_unique_constraint)
4895
keydef.flag|= HA_NULL_ARE_EQUAL;
4899
MI_CREATE_INFO create_info;
4900
memset(&create_info, 0, sizeof(create_info));
4902
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
4904
create_info.data_file_length= ~(uint64_t) 0;
4906
if ((error=mi_create(share->table_name.str, share->keys, &keydef,
4907
(uint) (*recinfo-start_recinfo),
4909
share->uniques, &uniquedef,
4911
HA_CREATE_TMP_TABLE)))
4913
file->print_error(error,MYF(0)); /* purecov: inspected */
4917
status_var_increment(in_use->status_var.created_tmp_disk_tables);
4918
share->db_record_offset= 1;
4925
void Table::free_tmp_table(THD *thd)
4927
MEM_ROOT own_root= mem_root;
4928
const char *save_proc_info;
4930
save_proc_info=thd->get_proc_info();
4931
thd->set_proc_info("removing tmp table");
4936
file->ha_drop_table(s->table_name.str);
4938
file->ha_delete_table(s->table_name.str);
4943
for (Field **ptr= field ; *ptr ; ptr++)
4945
free_io_cache(this);
4947
if (temp_pool_slot != MY_BIT_NONE)
4948
bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
4950
plugin_unlock(0, s->db_plugin);
4952
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
4953
thd->set_proc_info(save_proc_info);
4959
If a HEAP table gets full, create a MyISAM table and copy all rows
4963
bool create_myisam_from_heap(THD *thd, Table *table,
4964
MI_COLUMNDEF *start_recinfo,
4965
MI_COLUMNDEF **recinfo,
4966
int error, bool ignore_last_dupp_key_error)
4970
const char *save_proc_info;
4973
if (table->s->db_type() != heap_hton ||
4974
error != HA_ERR_RECORD_FILE_FULL)
4976
table->file->print_error(error,MYF(0));
4981
new_table.s= &share;
4982
new_table.s->db_plugin= ha_lock_engine(thd, myisam_hton);
4983
if (!(new_table.file= get_new_handler(&share, &new_table.mem_root,
4984
new_table.s->db_type())))
4985
return(1); // End of memory
4987
save_proc_info=thd->get_proc_info();
4988
thd->set_proc_info("converting HEAP to MyISAM");
4990
if (new_table.create_myisam_tmp_table(table->key_info, start_recinfo,
4991
recinfo, thd->lex->select_lex.options |
4994
if (new_table.open_tmp_table())
4996
if (table->file->indexes_are_disabled())
4997
new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
4998
table->file->ha_index_or_rnd_end();
4999
table->file->ha_rnd_init(1);
5002
new_table.file->extra(HA_EXTRA_NO_ROWS);
5003
new_table.no_rows=1;
5006
#ifdef TO_BE_DONE_LATER_IN_4_1
5008
To use start_bulk_insert() (which is new in 4.1) we need to find
5009
all places where a corresponding end_bulk_insert() should be put.
5011
table->file->info(HA_STATUS_VARIABLE); /* update table->file->stats.records */
5012
new_table.file->ha_start_bulk_insert(table->file->stats.records);
5014
/* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
5015
new_table.file->extra(HA_EXTRA_WRITE_CACHE);
5019
copy all old rows from heap table to MyISAM table
5020
This is the only code that uses record[1] to read/write but this
5021
is safe as this is a temporary MyISAM table without timestamp/autoincrement.
5023
while (!table->file->rnd_next(new_table.record[1]))
5025
write_err= new_table.file->ha_write_row(new_table.record[1]);
5029
/* copy row that filled HEAP table */
5030
if ((write_err=new_table.file->ha_write_row(table->record[0])))
5032
if (new_table.file->is_fatal_error(write_err, HA_CHECK_DUP) ||
5033
!ignore_last_dupp_key_error)
5037
/* remove heap table and change to use myisam table */
5038
(void) table->file->ha_rnd_end();
5039
(void) table->file->close(); // This deletes the table !
5042
plugin_unlock(0, table->s->db_plugin);
5043
share.db_plugin= my_plugin_lock(0, &share.db_plugin);
5044
new_table.s= table->s; // Keep old share
5048
table->file->change_table_ptr(table, table->s);
5049
table->use_all_columns();
5052
const char *new_proc_info=
5053
(!strcmp(save_proc_info,"Copying to tmp table") ?
5054
"Copying to tmp table on disk" : save_proc_info);
5055
thd->set_proc_info(new_proc_info);
5060
table->file->print_error(write_err, MYF(0));
5061
(void) table->file->ha_rnd_end();
5062
(void) new_table.file->close();
5064
new_table.file->ha_delete_table(new_table.s->table_name.str);
5066
delete new_table.file;
5067
thd->set_proc_info(save_proc_info);
5068
table->mem_root= new_table.mem_root;
5072
my_bitmap_map *Table::use_all_columns(MY_BITMAP *bitmap)
5074
my_bitmap_map *old= bitmap->bitmap;
5075
bitmap->bitmap= s->all_set.bitmap;
1399
void Table::restore_column_map(const boost::dynamic_bitset<>& old)
5079
void Table::restore_column_map(my_bitmap_map *old)
1401
for (boost::dynamic_bitset<>::size_type i= 0; i < old.size(); i++)
5081
read_set->bitmap= old;
1414
5084
uint32_t Table::find_shortest_key(const key_map *usable_keys)
1416
5086
uint32_t min_length= UINT32_MAX;
1417
5087
uint32_t best= MAX_KEY;
1418
if (usable_keys->any())
5088
if (!usable_keys->is_clear_all())
1420
for (uint32_t nr= 0; nr < getShare()->sizeKeys() ; nr++)
5090
for (uint32_t nr=0; nr < s->keys ; nr++)
1422
if (usable_keys->test(nr))
5092
if (usable_keys->is_set(nr))
1424
5094
if (key_info[nr].key_length < min_length)