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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
17
17
/* Some general useful functions */
19
#include <drizzled/server_includes.h>
20
28
#include <drizzled/error.h>
21
29
#include <drizzled/gettext.h>
23
#include <drizzled/tmp_table.h>
24
#include <drizzled/sj_tmp_table.h>
31
#include <drizzled/plugin/transactional_storage_engine.h>
32
#include <drizzled/plugin/authorization.h>
25
33
#include <drizzled/nested_join.h>
26
#include <drizzled/data_home.h>
27
34
#include <drizzled/sql_parse.h>
28
35
#include <drizzled/item/sum.h>
29
#include <drizzled/virtual_column_info.h>
30
36
#include <drizzled/table_list.h>
31
37
#include <drizzled/session.h>
32
38
#include <drizzled/sql_base.h>
39
#include <drizzled/sql_select.h>
33
40
#include <drizzled/field/blob.h>
34
41
#include <drizzled/field/varstring.h>
35
42
#include <drizzled/field/double.h>
43
#include <drizzled/message/table.pb.h>
44
#include <drizzled/sql_table.h>
45
#include <drizzled/charset.h>
46
#include <drizzled/internal/m_string.h>
47
#include <plugin/myisam/myisam.h>
48
#include <drizzled/plugin/storage_engine.h>
49
#include <drizzled/item/string.h>
50
#include <drizzled/item/int.h>
51
#include <drizzled/item/decimal.h>
52
#include <drizzled/item/float.h>
53
#include <drizzled/item/null.h>
54
#include <drizzled/temporal.h>
55
#include <drizzled/table/singular.h>
56
#include <drizzled/table_proto.h>
57
#include <drizzled/typelib.h>
58
#include <drizzled/sql_lex.h>
59
#include <drizzled/statistics_variables.h>
60
#include <drizzled/system_variables.h>
61
#include <drizzled/open_tables_state.h>
38
63
using namespace std;
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,
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);
67
extern plugin::StorageEngine *heap_engine;
68
extern plugin::StorageEngine *myisam_engine;
70
/* Functions defined in this cursor */
54
72
/*************************************************************************/
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
my_stpcpy(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
my_stpcpy(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= (MEM_ROOT **)pthread_getspecific(THR_MALLOC);
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
my_seek(file,pos,MY_SEEK_SET,MYF(0));
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
sql_print_warning(_("'%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
my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0));
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+= (my_stpcpy(keynames, (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*) my_malloc(n_length, MYF(MY_WME))))
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
my_seek(file,pos+288,MY_SEEK_SET,MYF(0));
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+com_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= names+(n_length+int_length);
787
memcpy(comment_pos, disk_buff+read_length-com_length-vcol_screen_length,
789
vcol_screen_pos= names+(n_length+int_length+com_length);
790
memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length,
793
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
794
if (share->fieldnames.count != share->fields)
796
fix_type_pointers(&interval_array, share->intervals, interval_count,
800
/* Set ENUM and SET lengths */
802
for (interval= share->intervals;
803
interval < share->intervals + interval_count;
806
uint32_t count= (uint) (interval->count + 1) * sizeof(uint);
807
if (!(interval->type_lengths= (uint32_t *) alloc_root(&share->mem_root,
810
for (count= 0; count < interval->count; count++)
812
char *val= (char*) interval->type_names[count];
813
interval->type_lengths[count]= strlen(val);
815
interval->type_lengths[count]= 0;
820
fix_type_pointers(&interval_array, &share->keynames, 1, &keynames);
822
/* Allocate handler */
823
if (!(handler_file= get_new_handler(share, session->mem_root,
827
record= share->default_values-1; /* Fieldstart = 1 */
828
if (share->null_field_first)
830
null_flags= null_pos= (unsigned char*) record+1;
831
null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
833
null_bytes below is only correct under the condition that
834
there are no bit fields. Correct values is set below after the
835
table struct is initialized
837
share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8;
840
use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH;
842
use_hash= !hash_init(&share->name_hash,
845
(hash_get_key) get_field_name,0,0);
847
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
849
uint32_t pack_flag, interval_nr, unireg_type, recpos, field_length;
850
uint32_t vcol_info_length=0;
851
enum_field_types field_type;
852
enum column_format_type column_format= COLUMN_FORMAT_TYPE_DEFAULT;
853
const CHARSET_INFO *charset= NULL;
855
virtual_column_info *vcol_info= NULL;
856
bool fld_is_stored= true;
858
if (field_extra_info)
860
char tmp= field_extra_info[i];
861
column_format= (enum column_format_type)
862
((tmp >> COLUMN_FORMAT_SHIFT) & COLUMN_FORMAT_MASK);
864
if (new_frm_ver >= 3)
866
/* new frm file in 4.1 */
867
field_length= uint2korr(strpos+3);
868
recpos= uint3korr(strpos+5);
869
pack_flag= uint2korr(strpos+8);
870
unireg_type= (uint) strpos[10];
871
interval_nr= (uint) strpos[12];
872
uint32_t comment_length=uint2korr(strpos+15);
873
field_type=(enum_field_types) (uint) strpos[13];
877
charset= &my_charset_bin;
878
else if (!(charset=get_charset((uint) strpos[14], MYF(0))))
880
error= 5; // Unknown or unavailable charset
881
errarg= (int) strpos[14];
885
if (field_type == DRIZZLE_TYPE_VIRTUAL)
887
assert(interval_nr); // Expect non-null expression
889
The interval_id byte in the .frm file stores the length of the
890
expression statement for a virtual column.
892
vcol_info_length= interval_nr;
897
comment.str= (char*) "";
902
comment.str= (char*) comment_pos;
903
comment.length= comment_length;
904
comment_pos+= comment_length;
906
if (vcol_info_length)
909
Get virtual column data stored in the .frm file as follows:
910
byte 1 = 1 (always 1 to allow for future extensions)
912
byte 3 = flags (as of now, 0 - no flags, 1 - field is physically stored)
913
byte 4-... = virtual column expression (text data)
915
vcol_info= new virtual_column_info();
916
if ((uint)vcol_screen_pos[0] != 1)
921
field_type= (enum_field_types) (unsigned char) vcol_screen_pos[1];
922
fld_is_stored= (bool) (uint) vcol_screen_pos[2];
923
vcol_info->expr_str.str= (char *)memdup_root(&share->mem_root,
925
(uint)FRM_VCOL_HEADER_SIZE,
927
(uint)FRM_VCOL_HEADER_SIZE);
928
vcol_info->expr_str.length= vcol_info_length-(uint)FRM_VCOL_HEADER_SIZE;
929
vcol_screen_pos+= vcol_info_length;
935
field_length= (uint) strpos[3];
936
recpos= uint2korr(strpos+4),
937
pack_flag= uint2korr(strpos+6);
938
pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
939
unireg_type= (uint) strpos[8];
940
interval_nr= (uint) strpos[10];
943
field_type= (enum_field_types) f_packtype(pack_flag);
944
if (f_is_binary(pack_flag))
947
Try to choose the best 4.1 type:
948
- for 4.0 "CHAR(N) BINARY" or "VARCHAR(N) BINARY"
949
try to find a binary collation for character set.
950
- for other types (e.g. BLOB) just use my_charset_bin.
952
if (!f_is_blob(pack_flag))
954
// 3.23 or 4.0 string
955
if (!(charset= get_charset_by_csname(share->table_charset->csname,
956
MY_CS_BINSORT, MYF(0))))
957
charset= &my_charset_bin;
960
charset= &my_charset_bin;
963
charset= share->table_charset;
964
memset(&comment, 0, sizeof(comment));
967
if (interval_nr && charset->mbminlen > 1)
969
/* Unescape UCS2 intervals from HEX notation */
970
TYPELIB *interval= share->intervals + interval_nr - 1;
971
unhex_type2(interval);
974
*field_ptr= reg_field=
975
make_field(share, record+recpos,
976
(uint32_t) field_length,
977
null_pos, null_bit_pos,
981
(Field::utype) MTYP_TYPENR(unireg_type),
983
share->intervals+interval_nr-1 :
985
share->fieldnames.type_names[i]);
986
if (!reg_field) // Not supported field type
989
goto err; /* purecov: inspected */
992
reg_field->flags|= ((uint)column_format << COLUMN_FORMAT_FLAGS);
993
reg_field->field_index= i;
994
reg_field->comment=comment;
995
reg_field->vcol_info= vcol_info;
996
reg_field->is_stored= fld_is_stored;
997
if (!(reg_field->flags & NOT_NULL_FLAG))
999
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
1002
if (f_no_default(pack_flag))
1003
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
1005
if (reg_field->unireg_check == Field::NEXT_NUMBER)
1006
share->found_next_number_field= field_ptr;
1007
if (share->timestamp_field == reg_field)
1008
share->timestamp_field_offset= i;
1011
(void) my_hash_insert(&share->name_hash,
1012
(unsigned char*) field_ptr); // never fail
1013
if (!reg_field->is_stored)
1015
share->stored_fields--;
1016
if (share->stored_rec_length>=recpos)
1017
share->stored_rec_length= recpos-1;
1020
*field_ptr=0; // End marker
1021
/* Sanity checks: */
1022
assert(share->fields>=share->stored_fields);
1023
assert(share->reclength>=share->stored_rec_length);
1025
/* Fix key->name and key_part->field */
1028
uint32_t primary_key=(uint) (find_type((char*) "PRIMARY",
1029
&share->keynames, 3) - 1);
1030
int64_t ha_option= handler_file->ha_table_flags();
1031
keyinfo= share->key_info;
1032
key_part= keyinfo->key_part;
1034
for (uint32_t key=0 ; key < share->keys ; key++,keyinfo++)
1036
uint32_t usable_parts= 0;
1037
keyinfo->name=(char*) share->keynames.type_names[key];
1039
if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1042
If the UNIQUE key doesn't have NULL columns and is not a part key
1043
declare this as a primary key.
1046
for (i=0 ; i < keyinfo->key_parts ;i++)
1048
uint32_t fieldnr= key_part[i].fieldnr;
1050
share->field[fieldnr-1]->null_ptr ||
1051
share->field[fieldnr-1]->key_length() !=
1054
primary_key=MAX_KEY; // Can't be used
1060
for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
1063
if (new_field_pack_flag <= 1)
1064
key_part->fieldnr= (uint16_t) find_field(share->field,
1065
share->default_values,
1066
(uint) key_part->offset,
1067
(uint) key_part->length);
1068
if (!key_part->fieldnr)
1070
error= 4; // Wrong file
1073
field= key_part->field= share->field[key_part->fieldnr-1];
1074
key_part->type= field->key_type();
1075
if (field->null_ptr)
1077
key_part->null_offset=(uint) ((unsigned char*) field->null_ptr -
1078
share->default_values);
1079
key_part->null_bit= field->null_bit;
1080
key_part->store_length+=HA_KEY_NULL_LENGTH;
1081
keyinfo->flags|=HA_NULL_PART_KEY;
1082
keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
1083
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
1085
if (field->type() == DRIZZLE_TYPE_BLOB ||
1086
field->real_type() == DRIZZLE_TYPE_VARCHAR)
1088
if (field->type() == DRIZZLE_TYPE_BLOB)
1089
key_part->key_part_flag|= HA_BLOB_PART;
1091
key_part->key_part_flag|= HA_VAR_LENGTH_PART;
1092
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
1093
key_part->store_length+=HA_KEY_BLOB_LENGTH;
1094
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
1096
if (i == 0 && key != primary_key)
1097
field->flags |= (((keyinfo->flags & HA_NOSAME) &&
1098
(keyinfo->key_parts == 1)) ?
1099
UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
1101
field->key_start.set_bit(key);
1102
if (field->key_length() == key_part->length &&
1103
!(field->flags & BLOB_FLAG))
1105
if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)
1107
share->keys_for_keyread.set_bit(key);
1108
field->part_of_key.set_bit(key);
1109
field->part_of_key_not_clustered.set_bit(key);
1111
if (handler_file->index_flags(key, i, 1) & HA_READ_ORDER)
1112
field->part_of_sortkey.set_bit(key);
1114
if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
1116
usable_parts++; // For FILESORT
1117
field->flags|= PART_KEY_FLAG;
1118
if (key == primary_key)
1120
field->flags|= PRI_KEY_FLAG;
1122
If this field is part of the primary key and all keys contains
1123
the primary key, then we can use any key to find this column
1125
if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX)
1127
field->part_of_key= share->keys_in_use;
1128
if (field->part_of_sortkey.is_set(key))
1129
field->part_of_sortkey= share->keys_in_use;
1132
if (field->key_length() != key_part->length)
1134
key_part->key_part_flag|= HA_PART_KEY_SEG;
1137
keyinfo->usable_key_parts= usable_parts; // Filesort
1139
set_if_bigger(share->max_key_length,keyinfo->key_length+
1140
keyinfo->key_parts);
1141
share->total_key_length+= keyinfo->key_length;
1143
MERGE tables do not have unique indexes. But every key could be
1144
an unique index on the underlying MyISAM table. (Bug #10400)
1146
if ((keyinfo->flags & HA_NOSAME) ||
1147
(ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE))
1148
set_if_bigger(share->max_unique_length,keyinfo->key_length);
1150
if (primary_key < MAX_KEY &&
1151
(share->keys_in_use.is_set(primary_key)))
1153
share->primary_key= primary_key;
1155
If we are using an integer as the primary key then allow the user to
1156
refer to it as '_rowid'
1158
if (share->key_info[primary_key].key_parts == 1)
1160
Field *field= share->key_info[primary_key].key_part[0].field;
1161
if (field && field->result_type() == INT_RESULT)
1163
/* note that fieldnr here (and rowid_field_offset) starts from 1 */
1164
share->rowid_field_offset= (share->key_info[primary_key].key_part[0].
1170
share->primary_key = MAX_KEY; // we do not have a primary key
1173
share->primary_key= MAX_KEY;
1177
if (new_field_pack_flag <= 1)
1179
/* Old file format with default as not null */
1180
uint32_t null_length= (share->null_fields+7)/8;
1181
memset(share->default_values + (null_flags - (unsigned char*) record),
1185
if (share->found_next_number_field)
1187
reg_field= *share->found_next_number_field;
1188
if ((int) (share->next_number_index= (uint)
1189
find_ref_key(share->key_info, share->keys,
1190
share->default_values, reg_field,
1191
&share->next_number_key_offset,
1192
&share->next_number_keypart)) < 0)
1194
/* Wrong field definition */
1199
reg_field->flags |= AUTO_INCREMENT_FLAG;
1202
if (share->blob_fields)
1207
/* Store offsets to blob fields to find them fast */
1208
if (!(share->blob_field= save=
1209
(uint*) alloc_root(&share->mem_root,
1210
(uint) (share->blob_fields* sizeof(uint)))))
1212
for (k=0, ptr= share->field ; *ptr ; ptr++, k++)
1214
if ((*ptr)->flags & BLOB_FLAG)
1220
the correct null_bytes can now be set, since bitfields have been taken
1223
share->null_bytes= (null_pos - (unsigned char*) null_flags +
1224
(null_bit_pos + 7) / 8);
1225
share->last_null_bit_pos= null_bit_pos;
1227
share->db_low_byte_first= handler_file->low_byte_first();
1228
share->column_bitmap_size= bitmap_buffer_size(share->fields);
1230
if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
1231
share->column_bitmap_size)))
1233
bitmap_init(&share->all_set, bitmaps, share->fields, false);
1234
bitmap_set_all(&share->all_set);
1236
delete handler_file;
1244
share->error= error;
1245
share->open_errno= my_errno;
1246
share->errarg= errarg;
1249
delete handler_file;
1250
hash_free(&share->name_hash);
1252
open_table_error(share, error, share->open_errno, errarg);
1254
} /* open_binary_frm */
1258
Clear flag GET_FIXED_FIELDS_FLAG in all fields of the table.
1259
This routine is used for error handling purposes.
1263
table Table object for which virtual columns are set-up
1268
static void clear_field_flag(Table *table)
1272
for (ptr= table->field; *ptr; ptr++)
1273
(*ptr)->flags&= (~GET_FIXED_FIELDS_FLAG);
1277
The function uses the feature in fix_fields where the flag
1278
GET_FIXED_FIELDS_FLAG is set for all fields in the item tree.
1279
This field must always be reset before returning from the function
1280
since it is used for other purposes as well.
1283
fix_fields_vcol_func()
1284
session The thread object
1285
func_item The item tree reference of the virtual columnfunction
1286
table The table object
1287
field_name The name of the processed field
1290
true An error occurred, something was wrong with the
1292
false Ok, a partition field array was created
1295
bool fix_fields_vcol_func(Session *session,
1298
const char *field_name)
1300
uint dir_length, home_dir_length;
1303
TableList *save_table_list, *save_first_table, *save_last_table;
1305
Name_resolution_context *context;
1306
const char *save_where;
1308
char db_name_string[FN_REFLEN];
1309
bool save_use_only_table_context;
1310
Field **ptr, *field;
1311
enum_mark_columns save_mark_used_columns= session->mark_used_columns;
1315
Set-up the TABLE_LIST object to be a list with a single table
1316
Set the object to zero to create NULL pointers and set alias
1317
and real name to table name and get database name from file name.
1320
bzero((void*)&tables, sizeof(TableList));
1321
tables.alias= tables.table_name= (char*) table->s->table_name.str;
1322
tables.table= table;
1323
tables.next_local= NULL;
1324
tables.next_name_resolution_table= NULL;
1325
memcpy(db_name_string,
1326
table->s->normalized_path.str,
1327
table->s->normalized_path.length);
1328
dir_length= dirname_length(db_name_string);
1329
db_name_string[dir_length - 1]= 0;
1330
home_dir_length= dirname_length(db_name_string);
1331
db_name= &db_name_string[home_dir_length];
1334
session->mark_used_columns= MARK_COLUMNS_NONE;
1336
context= session->lex->current_context();
1337
table->map= 1; //To ensure correct calculation of const item
1338
table->get_fields_in_item_tree= true;
1339
save_table_list= context->table_list;
1340
save_first_table= context->first_name_resolution_table;
1341
save_last_table= context->last_name_resolution_table;
1342
context->table_list= &tables;
1343
context->first_name_resolution_table= &tables;
1344
context->last_name_resolution_table= NULL;
1345
func_expr->walk(&Item::change_context_processor, 0, (unsigned char*) context);
1346
save_where= session->where;
1347
session->where= "virtual column function";
1349
/* Save the context before fixing the fields*/
1350
save_use_only_table_context= session->lex->use_only_table_context;
1351
session->lex->use_only_table_context= true;
1352
/* Fix fields referenced to by the virtual column function */
1353
error= func_expr->fix_fields(session, (Item**)0);
1354
/* Restore the original context*/
1355
session->lex->use_only_table_context= save_use_only_table_context;
1356
context->table_list= save_table_list;
1357
context->first_name_resolution_table= save_first_table;
1358
context->last_name_resolution_table= save_last_table;
1360
if (unlikely(error))
1362
clear_field_flag(table);
1365
session->where= save_where;
1367
Walk through the Item tree checking if all items are valid
1368
to be part of the virtual column
1370
error= func_expr->walk(&Item::check_vcol_func_processor, 0, NULL);
1373
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(0), field_name);
1374
clear_field_flag(table);
1377
if (unlikely(func_expr->const_item()))
1379
my_error(ER_CONST_EXPR_IN_VCOL, MYF(0));
1380
clear_field_flag(table);
1383
/* Ensure that this virtual column is not based on another virtual field. */
1385
while ((field= *(ptr++)))
1387
if ((field->flags & GET_FIXED_FIELDS_FLAG) &&
1390
my_error(ER_VCOL_BASED_ON_VCOL, MYF(0));
1391
clear_field_flag(table);
1396
Cleanup the fields marked with flag GET_FIXED_FIELDS_FLAG
1397
when calling fix_fields.
1399
clear_field_flag(table);
1403
table->get_fields_in_item_tree= false;
1404
session->mark_used_columns= save_mark_used_columns;
1405
table->map= 0; //Restore old value
1410
Unpack the definition of a virtual column
1413
unpack_vcol_info_from_frm()
1414
session Thread handler
1415
table Table with the checked field
1416
field Pointer to Field object
1417
open_mode Open table mode needed to determine
1418
which errors need to be generated in a failure
1419
error_reported updated flag for the caller that no other error
1420
messages are to be generated.
1426
bool unpack_vcol_info_from_frm(Session *session,
1429
LEX_STRING *vcol_expr,
1430
open_table_mode open_mode,
1431
bool *error_reported)
1436
Step 1: Construct a statement for the parser.
1437
The parsed string needs to take the following format:
1438
"PARSE_VCOL_EXPR (<expr_string_from_frm>)"
1440
char *vcol_expr_str;
1443
if (!(vcol_expr_str= (char*) alloc_root(&table->mem_root,
1445
parse_vcol_keyword.length + 3)))
1449
memcpy(vcol_expr_str,
1450
(char*) parse_vcol_keyword.str,
1451
parse_vcol_keyword.length);
1452
str_len= parse_vcol_keyword.length;
1453
memcpy(vcol_expr_str + str_len, "(", 1);
1455
memcpy(vcol_expr_str + str_len,
1456
(char*) vcol_expr->str,
1458
str_len+= vcol_expr->length;
1459
memcpy(vcol_expr_str + str_len, ")", 1);
1461
memcpy(vcol_expr_str + str_len, "\0", 1);
1463
Lex_input_stream lip(session, vcol_expr_str, str_len);
1466
Step 2: Setup session for parsing.
1467
1) make Item objects be created in the memory allocated for the Table
1468
object (not TABLE_SHARE)
1469
2) ensure that created Item's are not put on to session->free_list
1470
(which is associated with the parsed statement and hence cleared after
1472
3) setup a flag in the LEX structure to allow "PARSE_VCOL_EXPR"
1473
to be parsed as a SQL command.
1475
MEM_ROOT **root_ptr, *old_root;
1476
Item *backup_free_list= session->free_list;
1477
root_ptr= (MEM_ROOT **)pthread_getspecific(THR_MALLOC);
1478
old_root= *root_ptr;
1479
*root_ptr= &table->mem_root;
1480
session->free_list= NULL;
1481
session->lex->parse_vcol_expr= true;
1484
Step 3: Use the parser to build an Item object from.
1486
if (parse_sql(session, &lip))
1490
/* From now on use vcol_info generated by the parser. */
1491
field->vcol_info= session->lex->vcol_info;
1493
/* Validate the Item tree. */
1494
if (fix_fields_vcol_func(session,
1495
field->vcol_info->expr_item,
1499
if (open_mode == OTM_CREATE)
1502
During CREATE/ALTER TABLE it is ok to receive errors here.
1503
It is not ok if it happens during the opening of an frm
1504
file as part of a normal query.
1506
*error_reported= true;
1508
field->vcol_info= NULL;
1511
field->vcol_info->item_free_list= session->free_list;
1512
session->free_list= backup_free_list;
1513
*root_ptr= old_root;
1518
session->lex->parse_vcol_expr= false;
1519
session->free_items();
1520
*root_ptr= old_root;
1521
session->free_list= backup_free_list;
1527
Open a table based on a TABLE_SHARE
1530
open_table_from_share()
1531
session Thread handler
1532
share Table definition
1533
alias Alias for table
1534
db_stat open flags (for example HA_OPEN_KEYFILE|
1535
HA_OPEN_RNDFILE..) can be 0 (example in
1537
prgflag READ_ALL etc..
1538
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
1539
outparam result table
1540
open_mode One of OTM_OPEN|OTM_CREATE|OTM_ALTER
1541
if OTM_CREATE some errors are ignore
1542
if OTM_ALTER HA_OPEN is not called
1546
1 Error (see open_table_error)
1547
2 Error (see open_table_error)
1548
3 Wrong data in .frm file
1549
4 Error (see open_table_error)
1550
5 Error (see open_table_error: charset unavailable)
1551
7 Table definition has changed in engine
1554
int open_table_from_share(Session *session, TABLE_SHARE *share, const char *alias,
1555
uint32_t db_stat, uint32_t prgflag, uint32_t ha_open_flags,
1556
Table *outparam, open_table_mode open_mode)
1559
uint32_t records, i, bitmap_size;
1560
bool error_reported= false;
1561
unsigned char *record, *bitmaps;
1562
Field **field_ptr, **vfield_ptr;
1564
/* Parsing of partitioning information from .frm needs session->lex set up. */
1565
assert(session->lex->is_lex_started);
1568
memset(outparam, 0, sizeof(*outparam));
1569
outparam->in_use= session;
1571
outparam->db_stat= db_stat;
1572
outparam->write_row_record= NULL;
1574
init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
1576
if (!(outparam->alias= my_strdup(alias, MYF(MY_WME))))
1578
outparam->quick_keys.init();
1579
outparam->covering_keys.init();
1580
outparam->keys_in_use_for_query.init();
1582
/* Allocate handler */
1584
if (!(prgflag & OPEN_FRM_FILE_ONLY))
1586
if (!(outparam->file= get_new_handler(share, &outparam->mem_root,
1596
outparam->reginfo.lock_type= TL_UNLOCK;
1597
outparam->current_lock= F_UNLCK;
1599
if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN))
1601
if (prgflag & (READ_ALL+EXTRA_RECORD))
1604
if (!(record= (unsigned char*) alloc_root(&outparam->mem_root,
1605
share->rec_buff_length * records)))
1606
goto err; /* purecov: inspected */
1610
/* We are probably in hard repair, and the buffers should not be used */
1611
outparam->record[0]= outparam->record[1]= share->default_values;
1615
outparam->record[0]= record;
1617
outparam->record[1]= record+ share->rec_buff_length;
1619
outparam->record[1]= outparam->record[0]; // Safety
1624
We need this because when we read var-length rows, we are not updating
1625
bytes after end of varchar
1629
memcpy(outparam->record[0], share->default_values, share->rec_buff_length);
1630
memcpy(outparam->record[1], share->default_values, share->null_bytes);
1632
memcpy(outparam->record[1], share->default_values,
1633
share->rec_buff_length);
1637
if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root,
1638
(uint) ((share->fields+1)*
1640
goto err; /* purecov: inspected */
1642
outparam->field= field_ptr;
1644
record= (unsigned char*) outparam->record[0]-1; /* Fieldstart = 1 */
1645
if (share->null_field_first)
1646
outparam->null_flags= (unsigned char*) record+1;
1648
outparam->null_flags= (unsigned char*) (record+ 1+ share->reclength -
1651
/* Setup copy of fields from share, but use the right alias and record */
1652
for (i=0 ; i < share->fields; i++, field_ptr++)
1654
if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam)))
1657
(*field_ptr)= 0; // End marker
1659
if (share->found_next_number_field)
1660
outparam->found_next_number_field=
1661
outparam->field[(uint) (share->found_next_number_field - share->field)];
1662
if (share->timestamp_field)
1663
outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset];
1666
/* Fix key->name and key_part->field */
1667
if (share->key_parts)
1669
KEY *key_info, *key_info_end;
1670
KEY_PART_INFO *key_part;
1672
n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO);
1673
if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length)))
1675
outparam->key_info= key_info;
1676
key_part= (reinterpret_cast<KEY_PART_INFO*> (key_info+share->keys));
1678
memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys);
1679
memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) *
1682
for (key_info_end= key_info + share->keys ;
1683
key_info < key_info_end ;
1686
KEY_PART_INFO *key_part_end;
1688
key_info->table= outparam;
1689
key_info->key_part= key_part;
1691
for (key_part_end= key_part+ key_info->key_parts ;
1692
key_part < key_part_end ;
1695
Field *field= key_part->field= outparam->field[key_part->fieldnr-1];
1697
if (field->key_length() != key_part->length &&
1698
!(field->flags & BLOB_FLAG))
1701
We are using only a prefix of the column as a key:
1702
Create a new field for the key part that matches the index
1704
field= key_part->field=field->new_field(&outparam->mem_root,
1706
field->field_length= key_part->length;
1713
Process virtual columns, if any.
1715
if (not (vfield_ptr = (Field **) alloc_root(&outparam->mem_root,
1716
(uint) ((share->vfields+1)*
1720
outparam->vfield= vfield_ptr;
1722
for (field_ptr= outparam->field; *field_ptr; field_ptr++)
1724
if ((*field_ptr)->vcol_info)
1726
if (unpack_vcol_info_from_frm(session,
1729
&(*field_ptr)->vcol_info->expr_str,
1733
error= 4; // in case no error is reported
1736
*(vfield_ptr++)= *field_ptr;
1739
*vfield_ptr= NULL; // End marker
1740
/* Check virtual columns against table's storage engine. */
1741
if ((share->vfields && outparam->file) &&
1742
(not outparam->file->check_if_supported_virtual_columns()))
1744
my_error(ER_UNSUPPORTED_ACTION_ON_VIRTUAL_COLUMN,
1746
"Specified storage engine");
1747
error_reported= true;
1751
/* Allocate bitmaps */
1753
bitmap_size= share->column_bitmap_size;
1754
if (!(bitmaps= (unsigned char*) alloc_root(&outparam->mem_root, bitmap_size*3)))
1756
bitmap_init(&outparam->def_read_set,
1757
(my_bitmap_map*) bitmaps, share->fields, false);
1758
bitmap_init(&outparam->def_write_set,
1759
(my_bitmap_map*) (bitmaps+bitmap_size), share->fields, false);
1760
bitmap_init(&outparam->tmp_set,
1761
(my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, false);
1762
outparam->default_column_bitmaps();
1764
/* The table struct is now initialized; Open the table */
1766
if (db_stat && open_mode != OTM_ALTER)
1769
if ((ha_err= (outparam->file->
1770
ha_open(outparam, share->normalized_path.str,
1771
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
1772
(db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE :
1773
(db_stat & HA_WAIT_IF_LOCKED) ? HA_OPEN_WAIT_IF_LOCKED :
1774
(db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ?
1775
HA_OPEN_ABORT_IF_LOCKED :
1776
HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
1778
/* Set a flag if the table is crashed and it can be auto. repaired */
1779
share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) &&
1780
outparam->file->auto_repair() &&
1781
!(ha_open_flags & HA_OPEN_FOR_REPAIR));
1785
case HA_ERR_NO_SUCH_TABLE:
1787
The table did not exists in storage engine, use same error message
1788
as if the .frm file didn't exist
1795
Too many files opened, use same error message as if the .frm
1802
outparam->file->print_error(ha_err, MYF(0));
1803
error_reported= true;
1804
if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
1808
goto err; /* purecov: inspected */
1812
#if defined(HAVE_purify)
1813
memset(bitmaps, 0, bitmap_size*3);
1816
outparam->no_replicate= outparam->file;
1817
session->status_var.opened_tables++;
1822
if (!error_reported && !(prgflag & DONT_GIVE_ERROR))
1823
open_table_error(share, error, my_errno, 0);
1824
delete outparam->file;
1825
outparam->file= 0; // For easier error checking
1826
outparam->db_stat=0;
1827
free_root(&outparam->mem_root, MYF(0)); // Safe to call on zeroed root
1828
free((char*) outparam->alias);
1834
Free information allocated by openfrm
1838
table Table object to free
1839
free_share Is 1 if we also want to free table_share
1842
int closefrm(register Table *table, bool free_share)
1847
error=table->file->close();
1848
free((char*) table->alias);
1852
for (Field **ptr=table->field ; *ptr ; ptr++)
74
// @note this should all be the destructor
75
int Table::delete_table(bool free_share)
80
error= cursor->close();
85
for (Field **ptr=field ; *ptr ; ptr++)
1857
table->file= 0; /* For easier errorchecking */
1860
if (table->s->tmp_table == NO_TMP_TABLE)
1861
release_table_share(table->s, RELEASE_NORMAL);
1863
free_table_share(table->s);
1865
free_root(&table->mem_root, MYF(0));
103
mem_root.free_root(MYF(0));
107
void Table::resetTable(Session *session,
109
uint32_t db_stat_arg)
124
db_stat= db_stat_arg;
126
record[0]= (unsigned char *) NULL;
127
record[1]= (unsigned char *) NULL;
129
insert_values.clear();
131
next_number_field= NULL;
132
found_next_number_field= NULL;
133
timestamp_field= NULL;
135
pos_in_table_list= NULL;
145
derived_select_number= 0;
146
current_lock= F_UNLCK;
160
open_placeholder= false;
161
locked_by_name= false;
164
auto_increment_field_not_null= false;
165
alias_name_used= false;
168
quick_condition_rows= 0;
170
timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
175
covering_keys.reset();
180
keys_in_use_for_query.reset();
181
keys_in_use_for_group_by.reset();
182
keys_in_use_for_order_by.reset();
184
memset(quick_rows, 0, sizeof(ha_rows) * MAX_KEY);
185
memset(const_key_parts, 0, sizeof(ha_rows) * MAX_KEY);
187
memset(quick_key_parts, 0, sizeof(unsigned int) * MAX_KEY);
188
memset(quick_n_ranges, 0, sizeof(unsigned int) * MAX_KEY);
190
mem_root.init(TABLE_ALLOC_BLOCK_SIZE);
1870
195
/* Deallocate temporary blob storage */
1872
void free_blobs(register Table *table)
197
void free_blobs(Table *table)
1874
199
uint32_t *ptr, *end;
1875
200
for (ptr= table->getBlobField(), end=ptr + table->sizeBlobFields();
1878
((Field_blob*) table->field[*ptr])->free();
1882
/* Find where a form starts */
1883
/* if formname is NULL then only formnames is read */
1885
ulong get_form_pos(File file, unsigned char *head, TYPELIB *save_names)
1887
uint32_t a_length,names,length;
1888
unsigned char *pos,*buf;
1891
names=uint2korr(head+8);
1892
a_length=(names+2)*sizeof(char *); /* Room for two extra */
1897
save_names->type_names=0; /* Clear if error */
1901
length=uint2korr(head+4);
1902
my_seek(file,64L,MY_SEEK_SET,MYF(0));
1903
if (!(buf= (unsigned char*) my_malloc((size_t) length+a_length+names*4,
1905
my_read(file, buf+a_length, (size_t) (length+names*4),
1907
{ /* purecov: inspected */
1910
return(0L); /* purecov: inspected */
1912
pos= buf+a_length+length;
1913
ret_value=uint4korr(pos);
1918
free((unsigned char*) buf);
1921
memset(save_names, 0, sizeof(save_names));
1925
str=(char *) (buf+a_length);
1926
fix_type_pointers((const char ***) &buf,save_names,1,&str);
1933
Read string from a file with malloc
1936
We add an \0 at end of the read string to make reading of C strings easier
1939
int read_string(File file, unsigned char**to, size_t length)
1944
if (!(*to= (unsigned char*) my_malloc(length+1,MYF(MY_WME))) ||
1945
my_read(file, *to, length,MYF(MY_NABP)))
1950
return(1); /* purecov: inspected */
1952
*((char*) *to+length)= '\0';
1957
/* Add a new form to a form file */
1959
ulong make_new_entry(File file, unsigned char *fileinfo, TYPELIB *formnames,
1960
const char *newname)
1962
uint32_t i,bufflength,maxlength,n_length,length,names;
1963
ulong endpos,newpos;
1964
unsigned char buff[IO_SIZE];
1967
length=(uint) strlen(newname)+1;
1968
n_length=uint2korr(fileinfo+4);
1969
maxlength=uint2korr(fileinfo+6);
1970
names=uint2korr(fileinfo+8);
1971
newpos=uint4korr(fileinfo+10);
1973
if (64+length+n_length+(names+1)*4 > maxlength)
1976
int4store(fileinfo+10,newpos);
1977
endpos=(ulong) my_seek(file,0L,MY_SEEK_END,MYF(0));/* Copy from file-end */
1978
bufflength= (uint) (endpos & (IO_SIZE-1)); /* IO_SIZE is a power of 2 */
1980
while (endpos > maxlength)
1982
my_seek(file,(ulong) (endpos-bufflength),MY_SEEK_SET,MYF(0));
1983
if (my_read(file, buff, bufflength, MYF(MY_NABP+MY_WME)))
1985
my_seek(file,(ulong) (endpos-bufflength+IO_SIZE),MY_SEEK_SET,
1987
if ((my_write(file, buff,bufflength,MYF(MY_NABP+MY_WME))))
1989
endpos-=bufflength; bufflength=IO_SIZE;
1991
memset(buff, 0, IO_SIZE); /* Null new block */
1992
my_seek(file,(ulong) maxlength,MY_SEEK_SET,MYF(0));
1993
if (my_write(file,buff,bufflength,MYF(MY_NABP+MY_WME)))
1995
maxlength+=IO_SIZE; /* Fix old ref */
1996
int2store(fileinfo+6,maxlength);
1997
for (i=names, pos= (unsigned char*) *formnames->type_names+n_length-1; i-- ;
2000
endpos=uint4korr(pos)+IO_SIZE;
2001
int4store(pos,endpos);
2008
strxmov((char*) buff,"/",newname,"/",NULL);
2011
strxmov((char*) buff,newname,"/",NULL); /* purecov: inspected */
2012
my_seek(file,63L+(ulong) n_length,MY_SEEK_SET,MYF(0));
2013
if (my_write(file, buff, (size_t) length+1,MYF(MY_NABP+MY_WME)) ||
2014
(names && my_write(file,(unsigned char*) (*formnames->type_names+n_length-1),
2015
names*4, MYF(MY_NABP+MY_WME))) ||
2016
my_write(file, fileinfo+10, 4,MYF(MY_NABP+MY_WME)))
2017
return(0L); /* purecov: inspected */
2019
int2store(fileinfo+8,names+1);
2020
int2store(fileinfo+4,n_length+length);
2021
assert(ftruncate(file, newpos)==0);/* Append file with '\0' */
2023
} /* make_new_entry */
2026
/* error message when opening a form file */
2028
void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg)
2031
char buff[FN_REFLEN];
2032
myf errortype= ME_ERROR+ME_WAITTANG;
2037
if (db_errno == ENOENT)
2038
my_error(ER_NO_SUCH_TABLE, MYF(0), share->db.str, share->table_name.str);
2041
strxmov(buff, share->normalized_path.str, reg_ext, NULL);
2042
my_error((db_errno == EMFILE) ? ER_CANT_OPEN_FILE : ER_FILE_NOT_FOUND,
2043
errortype, buff, db_errno);
2049
const char *datext= "";
2051
if (share->db_type() != NULL)
2053
if ((file= get_new_handler(share, current_session->mem_root,
2056
if (!(datext= *file->bas_ext()))
2060
err_no= (db_errno == ENOENT) ? ER_FILE_NOT_FOUND : (db_errno == EAGAIN) ?
2061
ER_FILE_USED : ER_CANT_OPEN_FILE;
2062
strxmov(buff, share->normalized_path.str, datext, NULL);
2063
my_error(err_no,errortype, buff, db_errno);
2069
const char *csname= get_charset_name((uint) errarg);
2071
if (!csname || csname[0] =='?')
2073
snprintf(tmp, sizeof(tmp), "#%d", errarg);
2076
my_printf_error(ER_UNKNOWN_COLLATION,
2077
_("Unknown collation '%s' in table '%-.64s' definition"),
2078
MYF(0), csname, share->table_name.str);
2082
strxmov(buff, share->normalized_path.str, reg_ext, NULL);
2083
my_printf_error(ER_NOT_FORM_FILE,
2084
_("Table '%-.64s' was created with a different version "
2085
"of MySQL and cannot be read"),
2090
default: /* Better wrong error than none */
2092
strxmov(buff, share->normalized_path.str, reg_ext, NULL);
2093
my_error(ER_NOT_FORM_FILE, errortype, buff, 0);
2097
} /* open_table_error */
2101
** fix a str_type to a array type
2102
** typeparts separated with some char. differents types are separated
2107
fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint32_t types,
2110
char *type_name, *ptr;
2116
point_to_type->name=0;
2117
point_to_type->type_names= *array;
2119
if ((chr= *ptr)) /* Test if empty type */
2121
while ((type_name=strchr(ptr+1,chr)) != NULL)
2123
*((*array)++) = ptr+1;
2124
*type_name= '\0'; /* End string */
2127
ptr+=2; /* Skip end mark and last 0 */
2131
point_to_type->count= (uint) (*array - point_to_type->type_names);
2133
*((*array)++)= NULL; /* End of type */
2135
*names=ptr; /* Update end */
2137
} /* fix_type_pointers */
2140
TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings)
2142
TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
2145
result->count=strings.elements;
2147
uint32_t nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1);
2148
if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes)))
204
((Field_blob*) table->getField(*ptr))->free();
209
TYPELIB *typelib(memory::Root& mem_root, List<String> &strings)
211
TYPELIB *result= new (mem_root) TYPELIB;
212
result->count= strings.size();
214
result->type_names= (const char**) mem_root.alloc((sizeof(char*) + sizeof(uint32_t)) * (result->count + 1));
2150
215
result->type_lengths= (uint*) (result->type_names + result->count + 1);
2151
List_iterator<String> it(strings);
217
List<String>::iterator it(strings.begin());
2153
for (uint32_t i=0; (tmp=it++) ; i++)
219
for (uint32_t i= 0; (tmp= it++); i++)
2155
221
result->type_names[i]= tmp->ptr();
2156
222
result->type_lengths[i]= tmp->length();
2158
result->type_names[result->count]= 0; // End marker
225
result->type_names[result->count]= 0; // End marker
2159
226
result->type_lengths[result->count]= 0;
2165
Search after a field with given start & length
2166
If an exact field isn't found, return longest field with starts
2170
This is needed because in some .frm fields 'fieldnr' was saved wrong
2177
static uint32_t find_field(Field **fields, unsigned char *record, uint32_t start, uint32_t length)
2183
for (field= fields, i=1 ; *field ; i++,field++)
2185
if ((*field)->offset(record) == start)
2187
if ((*field)->key_length() == length)
2189
if (!pos || fields[pos-1]->pack_length() <
2190
(*field)->pack_length())
2198
231
/* Check that the integer is in the internal */
2200
int set_zone(register int nr, int min_zone, int max_zone)
233
int set_zone(int nr, int min_zone, int max_zone)
2202
235
if (nr<=min_zone)
2203
236
return (min_zone);