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
#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"
50
#include <drizzled/item/string.h>
51
#include <drizzled/item/int.h>
52
#include <drizzled/item/decimal.h>
53
#include <drizzled/item/float.h>
54
#include <drizzled/item/null.h>
55
#include <drizzled/temporal.h>
57
#include "drizzled/table/instance.h"
59
#include "drizzled/table_proto.h"
61
38
using namespace std;
66
extern pid_t current_pid;
67
extern plugin::StorageEngine *heap_engine;
68
extern plugin::StorageEngine *myisam_engine;
70
/* Functions defined in this cursor */
72
void open_table_error(TableShare *share, int error, int db_errno,
40
/* Keyword for parsing virtual column functions */
41
LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
43
/* Functions defined in this file */
45
void open_table_error(TABLE_SHARE *share, int error, int db_errno,
73
46
myf errortype, int errarg);
47
static int open_binary_frm(Session *session, TABLE_SHARE *share,
48
unsigned char *head, File file);
49
static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
50
uint32_t types, char **names);
51
static uint32_t find_field(Field **fields, unsigned char *record,
52
uint32_t start, uint32_t length);
75
54
/*************************************************************************/
77
// @note this should all be the destructor
78
int Table::delete_table(bool free_share)
56
/* Get column name from column hash */
58
static unsigned char *get_field_name(Field **buff, size_t *length, bool)
60
*length= (uint) strlen((*buff)->field_name);
61
return (unsigned char*) (*buff)->field_name;
66
Returns pointer to '.frm' extension of the file name.
73
Checks file name part starting with the rightmost '.' character,
74
and returns it if it is equal to '.frm'.
77
It is a good idea to get rid of this function modifying the code
78
to garantee that the functions presently calling fn_rext() always
79
get arguments in the same format: either with '.frm' or without '.frm'.
82
Pointer to the '.frm' extension. If there is no extension,
83
or extension is not '.frm', pointer at the end of file name.
86
char *fn_rext(char *name)
88
char *res= strrchr(name, '.');
89
if (res && !strcmp(res, reg_ext))
91
return name + strlen(name);
94
TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name)
99
if ((db->length == INFORMATION_SCHEMA_NAME.length()) &&
100
(my_strcasecmp(system_charset_info,
101
INFORMATION_SCHEMA_NAME.c_str(),
104
return TABLE_CATEGORY_INFORMATION;
107
return TABLE_CATEGORY_USER;
112
Allocate a setup TABLE_SHARE structure
116
TableList Take database and table name from there
117
key Table cache key (db \0 table_name \0...)
118
key_length Length of key
121
0 Error (out of memory)
125
TABLE_SHARE *alloc_table_share(TableList *table_list, char *key,
130
char *key_buff, *path_buff;
131
char path[FN_REFLEN];
132
uint32_t path_length;
134
path_length= build_table_filename(path, sizeof(path) - 1,
136
table_list->table_name, "", 0);
137
init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
138
if (multi_alloc_root(&mem_root,
139
&share, sizeof(*share),
140
&key_buff, key_length,
141
&path_buff, path_length + 1,
144
memset(share, 0, sizeof(*share));
146
share->set_table_cache_key(key_buff, key, key_length);
148
share->path.str= path_buff;
149
share->path.length= path_length;
150
strcpy(share->path.str, path);
151
share->normalized_path.str= share->path.str;
152
share->normalized_path.length= path_length;
154
share->version= refresh_version;
157
This constant is used to mark that no table map version has been
158
assigned. No arithmetic is done on the value: it will be
159
overwritten with a value taken from DRIZZLE_BIN_LOG.
161
share->table_map_version= UINT64_MAX;
164
Since alloc_table_share() can be called without any locking (for
165
example, ha_create_table... functions), we do not assign a table
166
map id here. Instead we assign a value that is not used
167
elsewhere, and then assign a table map id inside open_table()
168
under the protection of the LOCK_open mutex.
170
share->table_map_id= UINT32_MAX;
171
share->cached_row_logging_check= -1;
173
memcpy(&share->mem_root, &mem_root, sizeof(mem_root));
174
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
175
pthread_cond_init(&share->cond, NULL);
182
Initialize share for temporary tables
185
init_tmp_table_share()
186
session thread handle
188
key Table_cache_key, as generated from create_table_def_key.
189
must start with db name.
190
key_length Length of key
191
table_name Table name
192
path Path to file (possible in lower case) without .frm
195
This is different from alloc_table_share() because temporary tables
196
don't have to be shared between threads or put into the table def
197
cache, so we can do some things notable simpler and faster
199
If table is not put in session->temporary_tables (happens only when
200
one uses OPEN TEMPORARY) then one can specify 'db' as key and
201
use key_length= 0 as neither table_cache_key or key_length will be used).
204
void init_tmp_table_share(Session *session, TABLE_SHARE *share, const char *key,
205
uint32_t key_length, const char *table_name,
209
memset(share, 0, sizeof(*share));
210
init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
211
share->table_category= TABLE_CATEGORY_TEMPORARY;
212
share->tmp_table= INTERNAL_TMP_TABLE;
213
share->db.str= (char*) key;
214
share->db.length= strlen(key);
215
share->table_cache_key.str= (char*) key;
216
share->table_cache_key.length= key_length;
217
share->table_name.str= (char*) table_name;
218
share->table_name.length= strlen(table_name);
219
share->path.str= (char*) path;
220
share->normalized_path.str= (char*) path;
221
share->path.length= share->normalized_path.length= strlen(path);
224
Temporary tables are not replicated, but we set up these fields
225
anyway to be able to catch errors.
227
share->table_map_version= ~(uint64_t)0;
228
share->cached_row_logging_check= -1;
231
table_map_id is also used for MERGE tables to suppress repeated
232
compatibility checks.
234
share->table_map_id= (ulong) session->query_id;
241
Free table share and memory used by it
248
share->mutex must be locked when we come here if it's not a temp table
251
void free_table_share(TABLE_SHARE *share)
254
assert(share->ref_count == 0);
257
If someone is waiting for this to be deleted, inform it about this.
258
Don't do a delete until we know that no one is refering to this anymore.
260
if (share->tmp_table == NO_TMP_TABLE)
262
/* share->mutex is locked in release_table_share() */
263
while (share->waiting_on_cond)
265
pthread_cond_broadcast(&share->cond);
266
pthread_cond_wait(&share->cond, &share->mutex);
268
/* No thread refers to this anymore */
269
pthread_mutex_unlock(&share->mutex);
270
pthread_mutex_destroy(&share->mutex);
271
pthread_cond_destroy(&share->cond);
273
hash_free(&share->name_hash);
275
plugin_unlock(NULL, share->db_plugin);
276
share->db_plugin= NULL;
278
/* We must copy mem_root from share because share is allocated through it */
279
memcpy(&mem_root, &share->mem_root, sizeof(mem_root));
280
free_root(&mem_root, MYF(0)); // Free's share
285
Read table definition from a binary / text based .frm file
289
session Thread handler
290
share Fill this with table definition
291
db_flags Bit mask of the following flags: OPEN_VIEW
294
This function is called when the table definition is not cached in
296
The data is returned in 'share', which is alloced by
297
alloc_table_share().. The code assumes that share is initialized.
301
1 Error (see open_table_error)
302
2 Error (see open_table_error)
303
3 Wrong data in .frm file
304
4 Error (see open_table_error)
305
5 Error (see open_table_error: charset unavailable)
306
6 Unknown .frm version
309
int open_table_def(Session *session, TABLE_SHARE *share, uint32_t)
311
int error, table_type;
314
unsigned char head[64], *disk_buff;
317
MEM_ROOT **root_ptr, *old_root;
323
path.reserve(FN_REFLEN);
324
path.append(share->normalized_path.str);
325
path.append(reg_ext);
326
if ((file= open(path.c_str(), O_RDONLY)) < 0)
329
We don't try to open 5.0 unencoded name, if
330
- non-encoded name contains '@' signs,
331
because '@' can be misinterpreted.
332
It is not clear if '@' is escape character in 5.1,
333
or a normal character in 5.0.
335
- non-encoded db or table name contain "#mysql50#" prefix.
336
This kind of tables must have been opened only by the
339
if (strchr(share->table_name.str, '@') ||
340
!strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX,
341
MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
342
!strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX,
343
MYSQL50_TABLE_NAME_PREFIX_LENGTH))
346
/* Try unencoded 5.0 name */
348
char unpacked_path[FN_REFLEN];
350
path.append(drizzle_data_home);
352
path.append(share->db.str);
354
path.append(share->table_name.str);
355
path.append(reg_ext);
356
length= unpack_filename(unpacked_path, path.c_str()) - reg_ext_length;
358
The following is a safety test and should never fail
359
as the old file name should never be longer than the new one.
361
assert(length <= share->normalized_path.length);
363
If the old and the new names have the same length,
364
then table name does not have tricky characters,
365
so no need to check the old file name.
367
if (length == share->normalized_path.length ||
368
((file= open(unpacked_path, O_RDONLY)) < 0))
371
/* Unencoded 5.0 table name found */
372
unpacked_path[length]= '\0'; // Remove .frm extension
373
strcpy(share->normalized_path.str, unpacked_path);
374
share->normalized_path.length= length;
378
if (my_read(file, head, 64, MYF(MY_NABP)))
381
if (head[0] == (unsigned char) 254 && head[1] == 1)
383
if (head[2] == FRM_VER || head[2] == FRM_VER+1 ||
384
(head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4))
390
error= 6; // Unkown .frm version
397
/* No handling of text based files yet */
400
root_ptr= current_mem_root_ptr();
402
*root_ptr= &share->mem_root;
403
error= open_binary_frm(session, share, head, file);
410
share->table_category= get_table_category(& share->db, & share->table_name);
413
session->status_var.opened_shares++;
416
my_close(file, MYF(MY_WME));
419
if (error && !error_given)
422
open_table_error(share, error, (share->open_errno= my_errno), 0);
430
Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
433
static int open_binary_frm(Session *session, TABLE_SHARE *share, unsigned char *head,
436
int error, errarg= 0;
437
uint32_t new_frm_ver, field_pack_length, new_field_pack_flag;
438
uint32_t interval_count, interval_parts, read_length, int_length;
439
uint32_t db_create_options, keys, key_parts, n_length;
440
uint32_t key_info_length, com_length, null_bit_pos=0;
441
uint32_t vcol_screen_length;
442
uint32_t extra_rec_buf_length;
445
unsigned char forminfo[288];
446
char *keynames, *names, *comment_pos, *vcol_screen_pos;
447
unsigned char *record;
448
unsigned char *disk_buff, *strpos, *null_flags=NULL, *null_pos=NULL;
449
ulong pos, record_offset, *rec_per_key, rec_buff_length;
450
handler *handler_file= 0;
452
KEY_PART_INFO *key_part;
453
Field **field_ptr, *reg_field;
454
const char **interval_array;
455
enum legacy_db_type legacy_db_type;
456
my_bitmap_map *bitmaps;
457
unsigned char *buff= 0;
458
unsigned char *field_extra_info= 0;
460
new_field_pack_flag= head[27];
461
new_frm_ver= (head[2] - FRM_VER);
462
field_pack_length= new_frm_ver < 2 ? 11 : 17;
466
if (!(pos=get_form_pos(file,head,(TYPELIB*) 0)))
467
goto err; /* purecov: inspected */
468
lseek(file,pos,SEEK_SET);
469
if (my_read(file,forminfo,288,MYF(MY_NABP)))
472
legacy_db_type= DB_TYPE_FIRST_DYNAMIC;
473
assert(share->db_plugin == NULL);
475
if the storage engine is dynamic, no point in resolving it by its
476
dynamically allocated legacy_db_type. We will resolve it later by name.
478
if (legacy_db_type > DB_TYPE_UNKNOWN &&
479
legacy_db_type < DB_TYPE_FIRST_DYNAMIC)
480
share->db_plugin= ha_lock_engine(NULL,
481
ha_checktype(session, legacy_db_type, 0, 0));
482
share->db_create_options= db_create_options= uint2korr(head+30);
483
share->db_options_in_use= share->db_create_options;
484
share->mysql_version= uint4korr(head+51);
485
share->null_field_first= 0;
486
if (!head[32]) // New frm file in 3.23
488
share->avg_row_length= uint4korr(head+34);
489
share->transactional= (ha_choice) (head[39] & 3);
490
share->page_checksum= (ha_choice) ((head[39] >> 2) & 3);
491
share->row_type= (row_type) head[40];
492
share->block_size= uint4korr(head+43);
493
share->table_charset= get_charset((uint) head[38],MYF(0));
494
share->null_field_first= 1;
496
if (!share->table_charset)
498
/* unknown charset in head[38] or pre-3.23 frm */
499
if (use_mb(default_charset_info))
501
/* Warn that we may be changing the size of character columns */
502
errmsg_printf(ERRMSG_LVL_WARN, _("'%s' had no or invalid character set, "
503
"and default character set is multi-byte, "
504
"so character column sizes may have changed"),
507
share->table_charset= default_charset_info;
509
share->db_record_offset= 1;
510
if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
511
share->blob_ptr_size= portable_sizeof_char_ptr;
512
/* Set temporarily a good value for db_low_byte_first */
513
share->db_low_byte_first= true;
515
share->max_rows= uint4korr(head+18);
516
share->min_rows= uint4korr(head+22);
518
/* Read keyinformation */
519
key_info_length= (uint) uint2korr(head+28);
520
lseek(file,(ulong) uint2korr(head+6),SEEK_SET);
521
if (read_string(file,(unsigned char**) &disk_buff,key_info_length))
522
goto err; /* purecov: inspected */
523
if (disk_buff[0] & 0x80)
525
share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
526
share->key_parts= key_parts= uint2korr(disk_buff+2);
530
share->keys= keys= disk_buff[0];
531
share->key_parts= key_parts= disk_buff[1];
533
share->keys_for_keyread.init(0);
534
share->keys_in_use.init(keys);
536
n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
537
if (!(keyinfo = (KEY*) alloc_root(&share->mem_root,
538
n_length + uint2korr(disk_buff+4))))
539
goto err; /* purecov: inspected */
540
memset(keyinfo, 0, n_length);
541
share->key_info= keyinfo;
542
key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo+keys);
545
if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
546
sizeof(ulong*)*key_parts)))
549
for (i=0 ; i < keys ; i++, keyinfo++)
551
keyinfo->table= 0; // Updated in open_frm
552
if (new_frm_ver >= 3)
554
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
555
keyinfo->key_length= (uint) uint2korr(strpos+2);
556
keyinfo->key_parts= (uint) strpos[4];
557
keyinfo->algorithm= (enum ha_key_alg) strpos[5];
558
keyinfo->block_size= uint2korr(strpos+6);
562
keyinfo->key_part= key_part;
563
keyinfo->rec_per_key= rec_per_key;
564
for (j=keyinfo->key_parts ; j-- ; key_part++)
567
key_part->fieldnr= (uint16_t) (uint2korr(strpos) & FIELD_NR_MASK);
568
key_part->offset= (uint) uint2korr(strpos+2)-1;
569
key_part->key_type= (uint) uint2korr(strpos+5);
570
// key_part->field= (Field*) 0; // Will be fixed later
571
if (new_frm_ver >= 1)
573
key_part->key_part_flag= *(strpos+4);
574
key_part->length= (uint) uint2korr(strpos+7);
579
key_part->length= *(strpos+4);
580
key_part->key_part_flag=0;
581
if (key_part->length > 128)
583
key_part->length&=127; /* purecov: inspected */
584
key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
588
key_part->store_length=key_part->length;
591
keynames=(char*) key_part;
592
strpos+= (strcpy(keynames, (char*)strpos)+strlen((char*)strpos)-keynames)+1;
594
//reading index comments
595
for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
597
if (keyinfo->flags & HA_USES_COMMENT)
599
keyinfo->comment.length= uint2korr(strpos);
600
keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos+2,
601
keyinfo->comment.length);
602
strpos+= 2 + keyinfo->comment.length;
604
assert(test(keyinfo->flags & HA_USES_COMMENT) ==
605
(keyinfo->comment.length > 0));
608
share->reclength = uint2korr((head+16));
609
share->stored_rec_length= share->reclength;
611
record_offset= (ulong) (uint2korr(head+6)+
612
((uint2korr(head+14) == 0xffff ?
613
uint4korr(head+47) : uint2korr(head+14))));
615
if ((n_length= uint4korr(head+55)))
617
/* Read extra data segment */
618
unsigned char *next_chunk, *buff_end;
619
if (!(next_chunk= buff= (unsigned char*) malloc(n_length)))
621
if (pread(file, buff, n_length, record_offset + share->reclength) == 0)
625
share->connect_string.length= uint2korr(buff);
626
if (!(share->connect_string.str= strmake_root(&share->mem_root,
627
(char*) next_chunk + 2,
628
share->connect_string.
633
next_chunk+= share->connect_string.length + 2;
634
buff_end= buff + n_length;
635
if (next_chunk + 2 < buff_end)
637
uint32_t str_db_type_length= uint2korr(next_chunk);
639
name.str= (char*) next_chunk + 2;
640
name.length= str_db_type_length;
642
plugin_ref tmp_plugin= ha_resolve_by_name(session, &name);
643
if (tmp_plugin != NULL && !plugin_equals(tmp_plugin, share->db_plugin))
645
if (legacy_db_type > DB_TYPE_UNKNOWN &&
646
legacy_db_type < DB_TYPE_FIRST_DYNAMIC &&
647
legacy_db_type != ha_legacy_type(
648
plugin_data(tmp_plugin, handlerton *)))
650
/* bad file, legacy_db_type did not match the name */
655
tmp_plugin is locked with a local lock.
656
we unlock the old value of share->db_plugin before
657
replacing it with a globally locked version of tmp_plugin
659
plugin_unlock(NULL, share->db_plugin);
660
share->db_plugin= my_plugin_lock(NULL, &tmp_plugin);
662
else if (!tmp_plugin)
664
/* purecov: begin inspected */
666
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str);
671
next_chunk+= str_db_type_length + 2;
673
if (share->mysql_version >= 50110)
675
/* New auto_partitioned indicator introduced in 5.1.11 */
678
if (forminfo[46] == (unsigned char)255)
680
//reading long table comment
681
if (next_chunk + 2 > buff_end)
686
share->comment.length = uint2korr(next_chunk);
687
if (! (share->comment.str= strmake_root(&share->mem_root,
688
(char*)next_chunk + 2, share->comment.length)))
693
next_chunk+= 2 + share->comment.length;
695
assert(next_chunk <= buff_end);
696
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM_CGE)
699
New frm format in mysql_version 5.2.5 (originally in
700
mysql-5.1.22-ndb-6.2.5)
701
New column properties added:
702
COLUMN_FORMAT DYNAMIC|FIXED and STORAGE DISK|MEMORY
703
TABLESPACE name is now stored in frm
705
if (next_chunk >= buff_end)
707
if (share->mysql_version >= DRIZZLE_VERSION_TABLESPACE_IN_FRM)
714
const uint32_t format_section_header_size= 8;
715
uint32_t format_section_len= uint2korr(next_chunk+0);
717
field_extra_info= next_chunk + format_section_header_size + 1;
718
next_chunk+= format_section_len;
721
assert (next_chunk <= buff_end);
722
if (next_chunk > buff_end)
727
share->key_block_size= uint2korr(head+62);
730
extra_rec_buf_length= uint2korr(head+59);
731
rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length);
732
share->rec_buff_length= rec_buff_length;
733
if (!(record= (unsigned char *) alloc_root(&share->mem_root,
735
goto err; /* purecov: inspected */
736
share->default_values= record;
737
if (pread(file, record, (size_t) share->reclength, record_offset) == 0)
738
goto err; /* purecov: inspected */
740
lseek(file,pos+288,SEEK_SET);
742
share->fields= uint2korr(forminfo+258);
743
pos= uint2korr(forminfo+260); /* Length of all screens */
744
n_length= uint2korr(forminfo+268);
745
interval_count= uint2korr(forminfo+270);
746
interval_parts= uint2korr(forminfo+272);
747
int_length= uint2korr(forminfo+274);
748
share->null_fields= uint2korr(forminfo+282);
749
com_length= uint2korr(forminfo+284);
750
vcol_screen_length= uint2korr(forminfo+286);
752
share->stored_fields= share->fields;
753
if (forminfo[46] != (unsigned char)255)
755
share->comment.length= (int) (forminfo[46]);
756
share->comment.str= strmake_root(&share->mem_root, (char*) forminfo+47,
757
share->comment.length);
761
if (!(field_ptr = (Field **)
762
alloc_root(&share->mem_root,
763
(uint) ((share->fields+1)*sizeof(Field*)+
764
interval_count*sizeof(TYPELIB)+
765
(share->fields+interval_parts+
766
keys+3)*sizeof(char *)+
767
(n_length+int_length+
768
vcol_screen_length)))))
769
goto err; /* purecov: inspected */
771
share->field= field_ptr;
772
read_length=(uint) (share->fields * field_pack_length +
773
pos+ (uint) (n_length+int_length+com_length+
774
vcol_screen_length));
775
if (read_string(file,(unsigned char**) &disk_buff,read_length))
776
goto err; /* purecov: inspected */
777
strpos= disk_buff+pos;
779
share->intervals= (TYPELIB*) (field_ptr+share->fields+1);
780
interval_array= (const char **) (share->intervals+interval_count);
781
names= (char*) (interval_array+share->fields+interval_parts+keys+3);
783
share->intervals= 0; // For better debugging
784
memcpy(names, strpos+(share->fields*field_pack_length),
785
(uint) (n_length+int_length));
786
comment_pos= (char *)(disk_buff+read_length-com_length-vcol_screen_length);
787
vcol_screen_pos= names+(n_length+int_length);
788
memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length,
791
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
792
if (share->fieldnames.count != share->fields)
794
fix_type_pointers(&interval_array, share->intervals, interval_count,
798
/* Set ENUM and SET lengths */
800
for (interval= share->intervals;
801
interval < share->intervals + interval_count;
804
uint32_t count= (uint) (interval->count + 1) * sizeof(uint);
805
if (!(interval->type_lengths= (uint32_t *) alloc_root(&share->mem_root,
808
for (count= 0; count < interval->count; count++)
810
char *val= (char*) interval->type_names[count];
811
interval->type_lengths[count]= strlen(val);
813
interval->type_lengths[count]= 0;
818
fix_type_pointers(&interval_array, &share->keynames, 1, &keynames);
820
/* Allocate handler */
821
if (!(handler_file= get_new_handler(share, session->mem_root,
825
record= share->default_values-1; /* Fieldstart = 1 */
826
if (share->null_field_first)
828
null_flags= null_pos= (unsigned char*) record+1;
829
null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
831
null_bytes below is only correct under the condition that
832
there are no bit fields. Correct values is set below after the
833
table struct is initialized
835
share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8;
838
use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
840
use_hash= !hash_init(&share->name_hash,
843
(hash_get_key) get_field_name,0,0);
845
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
847
uint32_t pack_flag, interval_nr, unireg_type, recpos, field_length;
848
uint32_t vcol_info_length=0;
849
enum_field_types field_type;
850
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
851
const CHARSET_INFO *charset= NULL;
853
virtual_column_info *vcol_info= NULL;
854
bool fld_is_stored= true;
856
if (field_extra_info)
858
char tmp= field_extra_info[i];
859
column_format= (enum column_format_type)
860
((tmp >> COLUMN_FORMAT_SHIFT) & COLUMN_FORMAT_MASK);
862
if (new_frm_ver >= 3)
864
/* new frm file in 4.1 */
865
field_length= uint2korr(strpos+3);
866
recpos= uint3korr(strpos+5);
867
pack_flag= uint2korr(strpos+8);
868
unireg_type= (uint) strpos[10];
869
interval_nr= (uint) strpos[12];
870
uint32_t comment_length=uint2korr(strpos+15);
871
field_type=(enum_field_types) (uint) strpos[13];
875
charset= &my_charset_bin;
876
else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
878
error= 5; // Unknown or unavailable charset
879
errarg= (int) strpos[14];
883
if (field_type == DRIZZLE_TYPE_VIRTUAL)
885
assert(interval_nr); // Expect non-null expression
887
The interval_id byte in the .frm file stores the length of the
888
expression statement for a virtual column.
890
vcol_info_length= interval_nr;
895
comment.str= (char*) "";
900
comment.str= strmake_root(&share->mem_root, comment_pos, comment_length);
901
comment.length= comment_length;
902
comment_pos+= comment_length;
904
if (vcol_info_length)
907
Get virtual column data stored in the .frm file as follows:
908
byte 1 = 1 (always 1 to allow for future extensions)
910
byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
911
byte 4-... = virtual column expression (text data)
913
vcol_info= new virtual_column_info();
914
if ((uint)vcol_screen_pos[0] != 1)
919
field_type= (enum_field_types) (unsigned char) vcol_screen_pos[1];
920
fld_is_stored= (bool) (uint) vcol_screen_pos[2];
921
vcol_info->expr_str.str= (char *)memdup_root(&share->mem_root,
923
(uint)FRM_VCOL_HEADER_SIZE,
925
(uint)FRM_VCOL_HEADER_SIZE);
926
vcol_info->expr_str.length= vcol_info_length-(uint)FRM_VCOL_HEADER_SIZE;
927
vcol_screen_pos+= vcol_info_length;
933
field_length= (uint) strpos[3];
934
recpos= uint2korr(strpos+4),
935
pack_flag= uint2korr(strpos+6);
936
pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
937
unireg_type= (uint) strpos[8];
938
interval_nr= (uint) strpos[10];
941
field_type= (enum_field_types) f_packtype(pack_flag);
942
if (f_is_binary(pack_flag))
945
Try to choose the best 4.1 type:
946
- for 4.0 "CHAR(N) BINARY" or "VARCHAR(N) BINARY"
947
try to find a binary collation for character set.
948
- for other types (e.g. BLOB) just use my_charset_bin.
950
if (!f_is_blob(pack_flag))
952
// 3.23 or 4.0 string
953
if (!(charset= get_charset_by_csname(share->table_charset->csname,
954
MY_CS_BINSORT, MYF(0))))
955
charset= &my_charset_bin;
958
charset= &my_charset_bin;
961
charset= share->table_charset;
962
memset(&comment, 0, sizeof(comment));
965
if (interval_nr && charset->mbminlen > 1)
967
/* Unescape UCS2 intervals from HEX notation */
968
TYPELIB *interval= share->intervals + interval_nr - 1;
969
unhex_type2(interval);
972
*field_ptr= reg_field=
973
make_field(share, record+recpos,
974
(uint32_t) field_length,
975
null_pos, null_bit_pos,
979
(Field::utype) MTYP_TYPENR(unireg_type),
981
share->intervals+interval_nr-1 :
983
share->fieldnames.type_names[i]);
984
if (!reg_field) // Not supported field type
987
goto err; /* purecov: inspected */
990
reg_field->flags|= ((uint)column_format << COLUMN_FORMAT_FLAGS);
991
reg_field->field_index= i;
992
reg_field->comment=comment;
993
reg_field->vcol_info= vcol_info;
994
reg_field->is_stored= fld_is_stored;
995
if (!(reg_field->flags & NOT_NULL_FLAG))
997
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
1000
if (f_no_default(pack_flag))
1001
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
1003
if (reg_field->unireg_check == Field::NEXT_NUMBER)
1004
share->found_next_number_field= field_ptr;
1005
if (share->timestamp_field == reg_field)
1006
share->timestamp_field_offset= i;
1009
(void) my_hash_insert(&share->name_hash,
1010
(unsigned char*) field_ptr); // never fail
1011
if (!reg_field->is_stored)
1013
share->stored_fields--;
1014
if (share->stored_rec_length>=recpos)
1015
share->stored_rec_length= recpos-1;
1018
*field_ptr=0; // End marker
1019
/* Sanity checks: */
1020
assert(share->fields>=share->stored_fields);
1021
assert(share->reclength>=share->stored_rec_length);
1023
/* Fix key->name and key_part->field */
1026
uint32_t primary_key=(uint) (find_type((char*) "PRIMARY",
1027
&share->keynames, 3) - 1);
1028
int64_t ha_option= handler_file->ha_table_flags();
1029
keyinfo= share->key_info;
1030
key_part= keyinfo->key_part;
1032
for (uint32_t key=0 ; key < share->keys ; key++,keyinfo++)
1034
uint32_t usable_parts= 0;
1035
keyinfo->name=(char*) share->keynames.type_names[key];
1037
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1040
If the UNIQUE key doesn't have NULL columns and is not a part key
1041
declare this as a primary key.
1044
for (i=0 ; i < keyinfo->key_parts ;i++)
1046
uint32_t fieldnr= key_part[i].fieldnr;
1048
share->field[fieldnr-1]->null_ptr ||
1049
share->field[fieldnr-1]->key_length() !=
1052
primary_key=MAX_KEY; // Can't be used
1058
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
1061
if (new_field_pack_flag <= 1)
1062
key_part->fieldnr= (uint16_t) find_field(share->field,
1063
share->default_values,
1064
(uint) key_part->offset,
1065
(uint) key_part->length);
1066
if (!key_part->fieldnr)
1068
error= 4; // Wrong file
1071
field= key_part->field= share->field[key_part->fieldnr-1];
1072
key_part->type= field->key_type();
1073
if (field->null_ptr)
1075
key_part->null_offset=(uint) ((unsigned char*) field->null_ptr -
1076
share->default_values);
1077
key_part->null_bit= field->null_bit;
1078
key_part->store_length+=HA_KEY_NULL_LENGTH;
1079
keyinfo->flags|=HA_NULL_PART_KEY;
1080
keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
1081
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
1083
if (field->type() == DRIZZLE_TYPE_BLOB ||
1084
field->real_type() == DRIZZLE_TYPE_VARCHAR)
1086
if (field->type() == DRIZZLE_TYPE_BLOB)
1087
key_part->key_part_flag|= HA_BLOB_PART;
1089
key_part->key_part_flag|= HA_VAR_LENGTH_PART;
1090
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
1091
key_part->store_length+=HA_KEY_BLOB_LENGTH;
1092
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
1094
if (i == 0 && key != primary_key)
1095
field->flags |= (((keyinfo->flags & HA_NOSAME) &&
1096
(keyinfo->key_parts == 1)) ?
1097
UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
1099
field->key_start.set_bit(key);
1100
if (field->key_length() == key_part->length &&
1101
!(field->flags & BLOB_FLAG))
1103
if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
1105
share->keys_for_keyread.set_bit(key);
1106
field->part_of_key.set_bit(key);
1107
field->part_of_key_not_clustered.set_bit(key);
1109
if (handler_file->index_flags(key, i, 1) & HA_READ_ORDER)
1110
field->part_of_sortkey.set_bit(key);
1112
if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
1114
usable_parts++; // For FILESORT
1115
field->flags|= PART_KEY_FLAG;
1116
if (key == primary_key)
1118
field->flags|= PRI_KEY_FLAG;
1120
If this field is part of the primary key and all keys contains
1121
the primary key, then we can use any key to find this column
1123
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
1125
field->part_of_key= share->keys_in_use;
1126
if (field->part_of_sortkey.is_set(key))
1127
field->part_of_sortkey= share->keys_in_use;
1130
if (field->key_length() != key_part->length)
1132
key_part->key_part_flag|= HA_PART_KEY_SEG;
1135
keyinfo->usable_key_parts= usable_parts; // Filesort
1137
set_if_bigger(share->max_key_length,keyinfo->key_length+
1138
keyinfo->key_parts);
1139
share->total_key_length+= keyinfo->key_length;
1141
MERGE tables do not have unique indexes. But every key could be
1142
an unique index on the underlying MyISAM table. (Bug #10400)
1144
if ((keyinfo->flags & HA_NOSAME) ||
1145
(ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
1146
set_if_bigger(share->max_unique_length,keyinfo->key_length);
1148
if (primary_key < MAX_KEY &&
1149
(share->keys_in_use.is_set(primary_key)))
1151
share->primary_key= primary_key;
1153
If we are using an integer as the primary key then allow the user to
1154
refer to it as '_rowid'
1156
if (share->key_info[primary_key].key_parts == 1)
1158
Field *field= share->key_info[primary_key].key_part[0].field;
1159
if (field && field->result_type() == INT_RESULT)
1161
/* note that fieldnr here (and rowid_field_offset) starts from 1 */
1162
share->rowid_field_offset= (share->key_info[primary_key].key_part[0].
1168
share->primary_key = MAX_KEY; // we do not have a primary key
1171
share->primary_key= MAX_KEY;
1175
if (new_field_pack_flag <= 1)
1177
/* Old file format with default as not null */
1178
uint32_t null_length= (share->null_fields+7)/8;
1179
memset(share->default_values + (null_flags - (unsigned char*) record),
1183
if (share->found_next_number_field)
1185
reg_field= *share->found_next_number_field;
1186
if ((int) (share->next_number_index= (uint)
1187
find_ref_key(share->key_info, share->keys,
1188
share->default_values, reg_field,
1189
&share->next_number_key_offset,
1190
&share->next_number_keypart)) < 0)
1192
/* Wrong field definition */
1197
reg_field->flags |= AUTO_INCREMENT_FLAG;
1200
if (share->blob_fields)
1205
/* Store offsets to blob fields to find them fast */
1206
if (!(share->blob_field= save=
1207
(uint*) alloc_root(&share->mem_root,
1208
(uint) (share->blob_fields* sizeof(uint)))))
1210
for (k=0, ptr= share->field ; *ptr ; ptr++, k++)
1212
if ((*ptr)->flags & BLOB_FLAG)
1218
the correct null_bytes can now be set, since bitfields have been taken
1221
share->null_bytes= (null_pos - (unsigned char*) null_flags +
1222
(null_bit_pos + 7) / 8);
1223
share->last_null_bit_pos= null_bit_pos;
1225
share->db_low_byte_first= handler_file->low_byte_first();
1226
share->column_bitmap_size= bitmap_buffer_size(share->fields);
1228
if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1229
share->column_bitmap_size)))
1231
bitmap_init(&share->all_set, bitmaps, share->fields, false);
1232
bitmap_set_all(&share->all_set);
1234
delete handler_file;
1242
share->error= error;
1243
share->open_errno= my_errno;
1244
share->errarg= errarg;
1247
delete handler_file;
1248
hash_free(&share->name_hash);
1250
open_table_error(share, error, share->open_errno, errarg);
1252
} /* open_binary_frm */
1256
Clear flag GET_FIXED_FIELDS_FLAG in all fields of the table.
1257
This routine is used for error handling purposes.
1261
table Table object for which virtual columns are set-up
1266
static void clear_field_flag(Table *table)
1270
for (ptr= table->field; *ptr; ptr++)
1271
(*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
1275
The function uses the feature in fix_fields where the flag
1276
GET_FIXED_FIELDS_FLAG is set for all fields in the item tree.
1277
This field must always be reset before returning from the function
1278
since it is used for other purposes as well.
1281
fix_fields_vcol_func()
1282
session The thread object
1283
func_item The item tree reference of the virtual columnfunction
1284
table The table object
1285
field_name The name of the processed field
1288
true An error occurred, something was wrong with the
1290
false Ok, a partition field array was created
1293
bool fix_fields_vcol_func(Session *session,
1296
const char *field_name)
1298
uint dir_length, home_dir_length;
1301
TableList *save_table_list, *save_first_table, *save_last_table;
1303
Name_resolution_context *context;
1304
const char *save_where;
1306
char db_name_string[FN_REFLEN];
1307
bool save_use_only_table_context;
1308
Field **ptr, *field;
1309
enum_mark_columns save_mark_used_columns= session->mark_used_columns;
1313
Set-up the TABLE_LIST object to be a list with a single table
1314
Set the object to zero to create NULL pointers and set alias
1315
and real name to table name and get database name from file name.
1318
bzero((void*)&tables, sizeof(TableList));
1319
tables.alias= tables.table_name= (char*) table->s->table_name.str;
1320
tables.table= table;
1321
tables.next_local= NULL;
1322
tables.next_name_resolution_table= NULL;
1323
memcpy(db_name_string,
1324
table->s->normalized_path.str,
1325
table->s->normalized_path.length);
1326
dir_length= dirname_length(db_name_string);
1327
db_name_string[dir_length - 1]= 0;
1328
home_dir_length= dirname_length(db_name_string);
1329
db_name= &db_name_string[home_dir_length];
1332
session->mark_used_columns= MARK_COLUMNS_NONE;
1334
context= session->lex->current_context();
1335
table->map= 1; //To ensure correct calculation of const item
1336
table->get_fields_in_item_tree= true;
1337
save_table_list= context->table_list;
1338
save_first_table= context->first_name_resolution_table;
1339
save_last_table= context->last_name_resolution_table;
1340
context->table_list= &tables;
1341
context->first_name_resolution_table= &tables;
1342
context->last_name_resolution_table= NULL;
1343
func_expr->walk(&Item::change_context_processor, 0, (unsigned char*) context);
1344
save_where= session->where;
1345
session->where= "virtual column function";
1347
/* Save the context before fixing the fields*/
1348
save_use_only_table_context= session->lex->use_only_table_context;
1349
session->lex->use_only_table_context= true;
1350
/* Fix fields referenced to by the virtual column function */
1351
error= func_expr->fix_fields(session, (Item**)0);
1352
/* Restore the original context*/
1353
session->lex->use_only_table_context= save_use_only_table_context;
1354
context->table_list= save_table_list;
1355
context->first_name_resolution_table= save_first_table;
1356
context->last_name_resolution_table= save_last_table;
1358
if (unlikely(error))
1360
clear_field_flag(table);
1363
session->where= save_where;
1365
Walk through the Item tree checking if all items are valid
1366
to be part of the virtual column
1368
error= func_expr->walk(&Item::check_vcol_func_processor, 0, NULL);
1371
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
1372
clear_field_flag(table);
1375
if (unlikely(func_expr->const_item()))
1377
my_error(ER_CONST_EXPR_IN_VCOL, MYF(0));
1378
clear_field_flag(table);
1381
/* Ensure that this virtual column is not based on another virtual field. */
1383
while ((field= *(ptr++)))
1385
if ((field->flags & GET_FIXED_FIELDS_FLAG) &&
1388
my_error(ER_VCOL_BASED_ON_VCOL, MYF(0));
1389
clear_field_flag(table);
1394
Cleanup the fields marked with flag GET_FIXED_FIELDS_FLAG
1395
when calling fix_fields.
1397
clear_field_flag(table);
1401
table->get_fields_in_item_tree= false;
1402
session->mark_used_columns= save_mark_used_columns;
1403
table->map= 0; //Restore old value
1408
Unpack the definition of a virtual column
1411
unpack_vcol_info_from_frm()
1412
session Thread handler
1413
table Table with the checked field
1414
field Pointer to Field object
1415
open_mode Open table mode needed to determine
1416
which errors need to be generated in a failure
1417
error_reported updated flag for the caller that no other error
1418
messages are to be generated.
1424
bool unpack_vcol_info_from_frm(Session *session,
1427
LEX_STRING *vcol_expr,
1428
open_table_mode open_mode,
1429
bool *error_reported)
1434
Step 1: Construct a statement for the parser.
1435
The parsed string needs to take the following format:
1436
"PARSE_VCOL_EXPR (<expr_string_from_frm>)"
1438
char *vcol_expr_str;
1441
if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
1443
parse_vcol_keyword.length + 3)))
1447
memcpy(vcol_expr_str,
1448
(char*) parse_vcol_keyword.str,
1449
parse_vcol_keyword.length);
1450
str_len= parse_vcol_keyword.length;
1451
memcpy(vcol_expr_str + str_len, "(", 1);
1453
memcpy(vcol_expr_str + str_len,
1454
(char*) vcol_expr->str,
1456
str_len+= vcol_expr->length;
1457
memcpy(vcol_expr_str + str_len, ")", 1);
1459
memcpy(vcol_expr_str + str_len, "\0", 1);
1461
Lex_input_stream lip(session, vcol_expr_str, str_len);
1464
Step 2: Setup session for parsing.
1465
1) make Item objects be created in the memory allocated for the Table
1466
object (not TABLE_SHARE)
1467
2) ensure that created Item's are not put on to session->free_list
1468
(which is associated with the parsed statement and hence cleared after
1470
3) setup a flag in the LEX structure to allow "PARSE_VCOL_EXPR"
1471
to be parsed as a SQL command.
1473
MEM_ROOT **root_ptr, *old_root;
1474
Item *backup_free_list= session->free_list;
1475
root_ptr= current_mem_root_ptr();
1476
old_root= *root_ptr;
1477
*root_ptr= &table->mem_root;
1478
session->free_list= NULL;
1479
session->lex->parse_vcol_expr= true;
1482
Step 3: Use the parser to build an Item object from.
1484
if (parse_sql(session, &lip))
1488
/* From now on use vcol_info generated by the parser. */
1489
field->vcol_info= session->lex->vcol_info;
1491
/* Validate the Item tree. */
1492
if (fix_fields_vcol_func(session,
1493
field->vcol_info->expr_item,
1497
if (open_mode == OTM_CREATE)
1500
During CREATE/ALTER TABLE it is ok to receive errors here.
1501
It is not ok if it happens during the opening of an frm
1502
file as part of a normal query.
1504
*error_reported= true;
1506
field->vcol_info= NULL;
1509
field->vcol_info->item_free_list= session->free_list;
1510
session->free_list= backup_free_list;
1511
*root_ptr= old_root;
1516
session->lex->parse_vcol_expr= false;
1517
session->free_items();
1518
*root_ptr= old_root;
1519
session->free_list= backup_free_list;
1525
Open a table based on a TABLE_SHARE
1528
open_table_from_share()
1529
session Thread handler
1530
share Table definition
1531
alias Alias for table
1532
db_stat open flags (for example HA_OPEN_KEYFILE|
1533
HA_OPEN_RNDFILE..) can be 0 (example in
1535
prgflag READ_ALL etc..
1536
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
1537
outparam result table
1538
open_mode One of OTM_OPEN|OTM_CREATE|OTM_ALTER
1539
if OTM_CREATE some errors are ignore
1540
if OTM_ALTER HA_OPEN is not called
1544
1 Error (see open_table_error)
1545
2 Error (see open_table_error)
1546
3 Wrong data in .frm file
1547
4 Error (see open_table_error)
1548
5 Error (see open_table_error: charset unavailable)
1549
7 Table definition has changed in engine
1552
int open_table_from_share(Session *session, TABLE_SHARE *share, const char *alias,
1553
uint32_t db_stat, uint32_t prgflag, uint32_t ha_open_flags,
1554
Table *outparam, open_table_mode open_mode)
1557
uint32_t records, i, bitmap_size;
1558
bool error_reported= false;
1559
unsigned char *record, *bitmaps;
1560
Field **field_ptr, **vfield_ptr;
1562
/* Parsing of partitioning information from .frm needs session->lex set up. */
1563
assert(session->lex->is_lex_started);
1566
memset(outparam, 0, sizeof(*outparam));
1567
outparam->in_use= session;
1569
outparam->db_stat= db_stat;
1570
outparam->write_row_record= NULL;
1572
init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
1574
if (!(outparam->alias= strdup(alias)))
1576
outparam->quick_keys.init();
1577
outparam->covering_keys.init();
1578
outparam->keys_in_use_for_query.init();
1580
/* Allocate handler */
1582
if (!(prgflag & OPEN_FRM_FILE_ONLY))
1584
if (!(outparam->file= get_new_handler(share, &outparam->mem_root,
1594
outparam->reginfo.lock_type= TL_UNLOCK;
1595
outparam->current_lock= F_UNLCK;
1597
if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
1599
if (prgflag & (READ_ALL+EXTRA_RECORD))
1602
if (!(record= (unsigned char*) alloc_root(&outparam->mem_root,
1603
share->rec_buff_length * records)))
1604
goto err; /* purecov: inspected */
1608
/* We are probably in hard repair, and the buffers should not be used */
1609
outparam->record[0]= outparam->record[1]= share->default_values;
1613
outparam->record[0]= record;
1615
outparam->record[1]= record+ share->rec_buff_length;
1617
outparam->record[1]= outparam->record[0]; // Safety
1622
We need this because when we read var-length rows, we are not updating
1623
bytes after end of varchar
1627
memcpy(outparam->record[0], share->default_values, share->rec_buff_length);
1628
memcpy(outparam->record[1], share->default_values, share->null_bytes);
1630
memcpy(outparam->record[1], share->default_values,
1631
share->rec_buff_length);
1635
if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root,
1636
(uint) ((share->fields+1)*
1638
goto err; /* purecov: inspected */
1640
outparam->field= field_ptr;
1642
record= (unsigned char*) outparam->record[0]-1; /* Fieldstart = 1 */
1643
if (share->null_field_first)
1644
outparam->null_flags= (unsigned char*) record+1;
1646
outparam->null_flags= (unsigned char*) (record+ 1+ share->reclength -
1649
/* Setup copy of fields from share, but use the right alias and record */
1650
for (i=0 ; i < share->fields; i++, field_ptr++)
1652
if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam)))
1655
(*field_ptr)= 0; // End marker
1657
if (share->found_next_number_field)
1658
outparam->found_next_number_field=
1659
outparam->field[(uint) (share->found_next_number_field - share->field)];
1660
if (share->timestamp_field)
1661
outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
1664
/* Fix key->name and key_part->field */
1665
if (share->key_parts)
1667
KEY *key_info, *key_info_end;
1668
KEY_PART_INFO *key_part;
1670
n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO);
1671
if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length)))
1673
outparam->key_info= key_info;
1674
key_part= (reinterpret_cast<KEY_PART_INFO*> (key_info+share->keys));
1676
memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
1677
memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) *
1680
for (key_info_end= key_info + share->keys ;
1681
key_info < key_info_end ;
1684
KEY_PART_INFO *key_part_end;
1686
key_info->table= outparam;
1687
key_info->key_part= key_part;
1689
for (key_part_end= key_part+ key_info->key_parts ;
1690
key_part < key_part_end ;
1693
Field *field= key_part->field= outparam->field[key_part->fieldnr-1];
1695
if (field->key_length() != key_part->length &&
1696
!(field->flags & BLOB_FLAG))
1699
We are using only a prefix of the column as a key:
1700
Create a new field for the key part that matches the index
1702
field= key_part->field=field->new_field(&outparam->mem_root,
1704
field->field_length= key_part->length;
1711
Process virtual columns, if any.
1713
if (not (vfield_ptr = (Field **) alloc_root(&outparam->mem_root,
1714
(uint) ((share->vfields+1)*
1718
outparam->vfield= vfield_ptr;
1720
for (field_ptr= outparam->field; *field_ptr; field_ptr++)
1722
if ((*field_ptr)->vcol_info)
1724
if (unpack_vcol_info_from_frm(session,
1727
&(*field_ptr)->vcol_info->expr_str,
1731
error= 4; // in case no error is reported
1734
*(vfield_ptr++)= *field_ptr;
1737
*vfield_ptr= NULL; // End marker
1738
/* Check virtual columns against table's storage engine. */
1739
if ((share->vfields && outparam->file) &&
1740
(not outparam->file->check_if_supported_virtual_columns()))
1742
my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN,
1744
"Specified storage engine");
1745
error_reported= true;
1749
/* Allocate bitmaps */
1751
bitmap_size= share->column_bitmap_size;
1752
if (!(bitmaps= (unsigned char*) alloc_root(&outparam->mem_root, bitmap_size*3)))
1754
bitmap_init(&outparam->def_read_set,
1755
(my_bitmap_map*) bitmaps, share->fields, false);
1756
bitmap_init(&outparam->def_write_set,
1757
(my_bitmap_map*) (bitmaps+bitmap_size), share->fields, false);
1758
bitmap_init(&outparam->tmp_set,
1759
(my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, false);
1760
outparam->default_column_bitmaps();
1762
/* The table struct is now initialized; Open the table */
1764
if (db_stat && open_mode != OTM_ALTER)
1767
if ((ha_err= (outparam->file->
1768
ha_open(outparam, share->normalized_path.str,
1769
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
1770
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
1771
(db_stat & HA_WAIT_IF_LOCKED) ? HA_OPEN_WAIT_IF_LOCKED :
1772
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
1773
HA_OPEN_ABORT_IF_LOCKED :
1774
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
1776
/* Set a flag if the table is crashed and it can be auto. repaired */
1777
share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
1778
outparam->file->auto_repair() &&
1779
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
1783
case HA_ERR_NO_SUCH_TABLE:
1785
The table did not exists in storage engine, use same error message
1786
as if the .frm file didn't exist
1793
Too many files opened, use same error message as if the .frm
1800
outparam->file->print_error(ha_err, MYF(0));
1801
error_reported= true;
1802
if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
1806
goto err; /* purecov: inspected */
1810
#if defined(HAVE_purify)
1811
memset(bitmaps, 0, bitmap_size*3);
1814
outparam->no_replicate= outparam->file;
1815
session->status_var.opened_tables++;
1820
if (!error_reported && !(prgflag & DONT_GIVE_ERROR))
1821
open_table_error(share, error, my_errno, 0);
1822
delete outparam->file;
1823
outparam->file= 0; // For easier error checking
1824
outparam->db_stat=0;
1825
free_root(&outparam->mem_root, MYF(0)); // Safe to call on zeroed root
1826
free((char*) outparam->alias);
1830
/* close_temporary_tables' internal, 4 is due to uint4korr definition */
1831
uint32_t Table::tmpkeyval()
1833
return uint4korr(s->table_cache_key.str + s->table_cache_key.length - 4);
1837
Free information allocated by openfrm
1841
table Table object to free
1842
free_share Is 1 if we also want to free table_share
1845
int Table::closefrm(bool free_share)
83
error= cursor->close();
1850
error= file->close();
1851
free((char*) alias);
87
1855
for (Field **ptr=field ; *ptr ; ptr++)
94
cursor= 0; /* For easier errorchecking */
1860
file= 0; /* For easier errorchecking */
1863
if (s->tmp_table == NO_TMP_TABLE)
1864
release_table_share(s, RELEASE_NORMAL);
1866
free_table_share(s);
1868
free_root(&mem_root, MYF(0));
106
mem_root.free_root(MYF(0));
110
void Table::resetTable(Session *session,
112
uint32_t db_stat_arg)
125
db_stat= db_stat_arg;
128
record[0]= (unsigned char *) NULL;
129
record[1]= (unsigned char *) NULL;
131
insert_values.clear();
133
next_number_field= NULL;
134
found_next_number_field= NULL;
135
timestamp_field= NULL;
137
pos_in_table_list= NULL;
147
derived_select_number= 0;
148
current_lock= F_UNLCK;
162
open_placeholder= false;
163
locked_by_name= false;
166
auto_increment_field_not_null= false;
167
alias_name_used= false;
170
quick_condition_rows= 0;
172
timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
177
covering_keys.reset();
182
keys_in_use_for_query.reset();
183
keys_in_use_for_group_by.reset();
184
keys_in_use_for_order_by.reset();
186
memset(quick_rows, 0, sizeof(ha_rows) * MAX_KEY);
187
memset(const_key_parts, 0, sizeof(ha_rows) * MAX_KEY);
189
memset(quick_key_parts, 0, sizeof(unsigned int) * MAX_KEY);
190
memset(quick_n_ranges, 0, sizeof(unsigned int) * MAX_KEY);
192
memory::init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
197
1874
/* Deallocate temporary blob storage */
1398
4355
session->mem_root= mem_root_save;
4356
table->free_tmp_table(session); /* purecov: inspected */
4357
if (temp_pool_slot != MY_BIT_NONE)
4358
bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
4359
return(NULL); /* purecov: inspected */
1404
4362
/****************************************************************************/
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;
4365
Create a reduced Table object with properly set up Field list from a
4366
list of field definitions.
4368
The created table doesn't have a table handler associated with
4369
it, has no keys, no group/distinct, no copy_funcs array.
4370
The sole purpose of this Table object is to use the power of Field
4371
class to read/write data to/from table->record[0]. Then one can store
4372
the record in any container (RB tree, hash, etc).
4373
The table is created in Session mem_root, so are the table's fields.
4374
Consequently, if you don't BLOB fields, you don't need to free it.
4376
@param session connection handle
4377
@param field_list list of column definitions
4380
0 if out of memory, Table object in case of success
4383
Table *create_virtual_tmp_table(Session *session, List<Create_field> &field_list)
4385
uint32_t field_count= field_list.elements;
4386
uint32_t blob_count= 0;
4388
Create_field *cdef; /* column definition */
4389
uint32_t record_length= 0;
4390
uint32_t null_count= 0; /* number of columns which may be null */
4391
uint32_t null_pack_length; /* NULL representation array length */
4392
uint32_t *blob_field;
4393
unsigned char *bitmaps;
4397
if (!multi_alloc_root(session->mem_root,
4398
&table, sizeof(*table),
4399
&share, sizeof(*share),
4400
&field, (field_count + 1) * sizeof(Field*),
4401
&blob_field, (field_count+1) *sizeof(uint),
4402
&bitmaps, bitmap_buffer_size(field_count)*2,
4406
memset(table, 0, sizeof(*table));
4407
memset(share, 0, sizeof(*share));
4408
table->field= field;
4410
share->blob_field= blob_field;
4411
share->fields= field_count;
4412
share->blob_ptr_size= portable_sizeof_char_ptr;
4413
table->setup_tmp_table_column_bitmaps(bitmaps);
4415
/* Create all fields and calculate the total length of record */
4416
List_iterator_fast<Create_field> it(field_list);
4417
while ((cdef= it++))
4419
*field= make_field(share, 0, cdef->length,
4420
(unsigned char*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
4421
f_maybe_null(cdef->pack_flag) ? 1 : 0,
4422
cdef->pack_flag, cdef->sql_type, cdef->charset,
4424
cdef->interval, cdef->field_name);
4427
(*field)->init(table);
4428
record_length+= (*field)->pack_length();
4429
if (! ((*field)->flags & NOT_NULL_FLAG))
4432
if ((*field)->flags & BLOB_FLAG)
4433
share->blob_field[blob_count++]= (uint) (field - table->field);
4437
*field= NULL; /* mark the end of the list */
4438
share->blob_field[blob_count]= 0; /* mark the end of the list */
4439
share->blob_fields= blob_count;
4441
null_pack_length= (null_count + 7)/8;
4442
share->reclength= record_length + null_pack_length;
4443
share->rec_buff_length= ALIGN_SIZE(share->reclength + 1);
4444
table->record[0]= (unsigned char*) session->alloc(share->rec_buff_length);
4445
if (!table->record[0])
4448
if (null_pack_length)
4450
table->null_flags= (unsigned char*) table->record[0];
4451
share->null_fields= null_count;
4452
share->null_bytes= null_pack_length;
4455
table->in_use= session; /* field->reset() may access table->in_use */
4457
/* Set up field pointers */
4458
unsigned char *null_pos= table->record[0];
4459
unsigned char *field_pos= null_pos + share->null_bytes;
4460
uint32_t null_bit= 1;
4462
for (field= table->field; *field; ++field)
4464
Field *cur_field= *field;
4465
if ((cur_field->flags & NOT_NULL_FLAG))
4466
cur_field->move_field(field_pos);
4469
cur_field->move_field(field_pos, (unsigned char*) null_pos, null_bit);
4471
if (null_bit == (1 << 8))
4479
field_pos+= cur_field->pack_length();
4484
for (field= table->field; *field; ++field)
4485
delete *field; /* just invokes field destructor */
4490
bool Table::open_tmp_table()
4493
if ((error=file->ha_open(this, s->table_name.str,O_RDWR,
4494
HA_OPEN_TMP_TABLE | HA_OPEN_INTERNAL_TABLE)))
4496
file->print_error(error,MYF(0)); /* purecov: inspected */
4500
(void) file->extra(HA_EXTRA_QUICK); /* Faster */
4506
Create MyISAM temporary table
4509
create_myisam_tmp_table()
4510
keyinfo Description of the index (there is always one index)
4511
start_recinfo MyISAM's column descriptions
4512
recinfo INOUT End of MyISAM's column descriptions
4516
Create a MyISAM temporary table according to passed description. The is
4517
assumed to have one unique index or constraint.
4519
The passed array or MI_COLUMNDEF structures must have this form:
4521
1. 1-byte column (afaiu for 'deleted' flag) (note maybe not 1-byte
4522
when there are many nullable columns)
4524
3. One free MI_COLUMNDEF element (*recinfo points here)
4526
This function may use the free element to create hash column for unique
4534
bool Table::create_myisam_tmp_table(KEY *keyinfo,
4535
MI_COLUMNDEF *start_recinfo,
4536
MI_COLUMNDEF **recinfo,
4541
MI_UNIQUEDEF uniquedef;
4542
TABLE_SHARE *share= s;
4545
{ // Get keys for ni_create
4546
bool using_unique_constraint=0;
4547
HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&this->mem_root,
4548
sizeof(*seg) * keyinfo->key_parts);
4552
memset(seg, 0, sizeof(*seg) * keyinfo->key_parts);
4553
if (keyinfo->key_length >= file->max_key_length() ||
4554
keyinfo->key_parts > file->max_key_parts() ||
4557
/* Can't create a key; Make a unique constraint instead of a key */
4560
using_unique_constraint=1;
4561
memset(&uniquedef, 0, sizeof(uniquedef));
4562
uniquedef.keysegs=keyinfo->key_parts;
4564
uniquedef.null_are_equal=1;
4566
/* Create extra column for hash value */
4567
memset(*recinfo, 0, sizeof(**recinfo));
4568
(*recinfo)->type= FIELD_CHECK;
4569
(*recinfo)->length=MI_UNIQUE_HASH_LENGTH;
4571
share->reclength+=MI_UNIQUE_HASH_LENGTH;
4575
/* Create an unique key */
4576
memset(&keydef, 0, sizeof(keydef));
4577
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
4578
keydef.keysegs= keyinfo->key_parts;
4581
for (uint32_t i=0; i < keyinfo->key_parts ; i++,seg++)
4583
Field *key_field=keyinfo->key_part[i].field;
4585
seg->language= key_field->charset()->number;
4586
seg->length= keyinfo->key_part[i].length;
4587
seg->start= keyinfo->key_part[i].offset;
4588
if (key_field->flags & BLOB_FLAG)
4591
((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
4592
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
4593
seg->bit_start= (uint8_t)(key_field->pack_length()
4594
- share->blob_ptr_size);
4595
seg->flag= HA_BLOB_PART;
4596
seg->length=0; // Whole blob in unique constraint
4600
seg->type= keyinfo->key_part[i].type;
4602
if (!(key_field->flags & NOT_NULL_FLAG))
4604
seg->null_bit= key_field->null_bit;
4605
seg->null_pos= (uint) (key_field->null_ptr - (unsigned char*) record[0]);
4607
We are using a GROUP BY on something that contains NULL
4608
In this case we have to tell MyISAM that two NULL should
4609
on INSERT be regarded at the same value
4611
if (!using_unique_constraint)
4612
keydef.flag|= HA_NULL_ARE_EQUAL;
4616
MI_CREATE_INFO create_info;
4617
memset(&create_info, 0, sizeof(create_info));
4619
if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
4621
create_info.data_file_length= ~(uint64_t) 0;
4623
if ((error=mi_create(share->table_name.str, share->keys, &keydef,
4624
(uint) (*recinfo-start_recinfo),
4626
share->uniques, &uniquedef,
4628
HA_CREATE_TMP_TABLE)))
4630
file->print_error(error,MYF(0)); /* purecov: inspected */
4634
status_var_increment(in_use->status_var.created_tmp_disk_tables);
4635
share->db_record_offset= 1;
4642
void Table::free_tmp_table(Session *session)
4644
MEM_ROOT own_root= mem_root;
4645
const char *save_proc_info;
4647
save_proc_info=session->get_proc_info();
4648
session->set_proc_info("removing tmp table");
4653
file->ha_drop_table(s->table_name.str);
4655
file->ha_delete_table(s->table_name.str);
4660
for (Field **ptr= field ; *ptr ; ptr++)
4662
free_io_cache(this);
4664
if (temp_pool_slot != MY_BIT_NONE)
4665
bitmap_lock_clear_bit(&temp_pool, temp_pool_slot);
4667
plugin_unlock(0, s->db_plugin);
4669
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
4670
session->set_proc_info(save_proc_info);
4676
If a HEAP table gets full, create a MyISAM table and copy all rows
4680
bool create_myisam_from_heap(Session *session, Table *table,
4681
MI_COLUMNDEF *start_recinfo,
4682
MI_COLUMNDEF **recinfo,
4683
int error, bool ignore_last_dupp_key_error)
4687
const char *save_proc_info;
4690
if (table->s->db_type() != heap_hton ||
4691
error != HA_ERR_RECORD_FILE_FULL)
4693
table->file->print_error(error,MYF(0));
4698
new_table.s= &share;
4699
new_table.s->db_plugin= ha_lock_engine(session, myisam_hton);
4700
if (!(new_table.file= get_new_handler(&share, &new_table.mem_root,
4701
new_table.s->db_type())))
4702
return(1); // End of memory
4704
save_proc_info=session->get_proc_info();
4705
session->set_proc_info("converting HEAP to MyISAM");
4707
if (new_table.create_myisam_tmp_table(table->key_info, start_recinfo,
4708
recinfo, session->lex->select_lex.options |
4711
if (new_table.open_tmp_table())
4713
if (table->file->indexes_are_disabled())
4714
new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
4715
table->file->ha_index_or_rnd_end();
4716
table->file->ha_rnd_init(1);
4719
new_table.file->extra(HA_EXTRA_NO_ROWS);
4720
new_table.no_rows=1;
4723
/* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
4724
new_table.file->extra(HA_EXTRA_WRITE_CACHE);
4727
copy all old rows from heap table to MyISAM table
4728
This is the only code that uses record[1] to read/write but this
4729
is safe as this is a temporary MyISAM table without timestamp/autoincrement.
4731
while (!table->file->rnd_next(new_table.record[1]))
4733
write_err= new_table.file->ha_write_row(new_table.record[1]);
4737
/* copy row that filled HEAP table */
4738
if ((write_err=new_table.file->ha_write_row(table->record[0])))
4740
if (new_table.file->is_fatal_error(write_err, HA_CHECK_DUP) ||
4741
!ignore_last_dupp_key_error)
4745
/* remove heap table and change to use myisam table */
4746
(void) table->file->ha_rnd_end();
4747
(void) table->file->close(); // This deletes the table !
4750
plugin_unlock(0, table->s->db_plugin);
4751
share.db_plugin= my_plugin_lock(0, &share.db_plugin);
4752
new_table.s= table->s; // Keep old share
4756
table->file->change_table_ptr(table, table->s);
4757
table->use_all_columns();
4760
const char *new_proc_info=
4761
(!strcmp(save_proc_info,"Copying to tmp table") ?
4762
"Copying to tmp table on disk" : save_proc_info);
4763
session->set_proc_info(new_proc_info);
4768
table->file->print_error(write_err, MYF(0));
4769
(void) table->file->ha_rnd_end();
4770
(void) new_table.file->close();
4772
new_table.file->ha_delete_table(new_table.s->table_name.str);
4774
delete new_table.file;
4775
session->set_proc_info(save_proc_info);
4776
table->mem_root= new_table.mem_root;
4780
my_bitmap_map *Table::use_all_columns(MY_BITMAP *bitmap)
4782
my_bitmap_map *old= bitmap->bitmap;
4783
bitmap->bitmap= s->all_set.bitmap;
1421
void Table::restore_column_map(const boost::dynamic_bitset<>& old)
4787
void Table::restore_column_map(my_bitmap_map *old)
1423
for (boost::dynamic_bitset<>::size_type i= 0; i < old.size(); i++)
4789
read_set->bitmap= old;
1436
4792
uint32_t Table::find_shortest_key(const key_map *usable_keys)
1438
4794
uint32_t min_length= UINT32_MAX;
1439
4795
uint32_t best= MAX_KEY;
1440
if (usable_keys->any())
4796
if (!usable_keys->is_clear_all())
1442
for (uint32_t nr= 0; nr < getShare()->sizeKeys() ; nr++)
4798
for (uint32_t nr=0; nr < s->keys ; nr++)
1444
if (usable_keys->test(nr))
4800
if (usable_keys->is_set(nr))
1446
4802
if (key_info[nr].key_length < min_length)