summaryrefslogtreecommitdiff
path: root/sql/table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/table.cc')
-rw-r--r--sql/table.cc400
1 files changed, 214 insertions, 186 deletions
diff --git a/sql/table.cc b/sql/table.cc
index 912dd0dfa54..eed1de9bb35 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -653,6 +653,184 @@ err_not_open:
DBUG_RETURN(share->error);
}
+static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
+ uint keys, KEY *keyinfo,
+ uint new_frm_ver, uint &ext_key_parts,
+ TABLE_SHARE *share, uint len,
+ KEY *first_keyinfo, char* &keynames)
+{
+ uint i, j, n_length;
+ KEY_PART_INFO *key_part= NULL;
+ ulong *rec_per_key= NULL;
+ KEY_PART_INFO *first_key_part= NULL;
+ uint first_key_parts= 0;
+
+ if (!keys)
+ {
+ if (!(keyinfo = (KEY*) alloc_root(&share->mem_root, len)))
+ return 1;
+ bzero((char*) keyinfo, len);
+ key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo);
+ }
+
+ /*
+ If share->use_ext_keys is set to TRUE we assume that any key
+ can be extended by the components of the primary key whose
+ definition is read first from the frm file.
+ For each key only those fields of the assumed primary key are
+ added that are not included in the proper key definition.
+ If after all it turns out that there is no primary key the
+ added components are removed from each key.
+
+ When in the future we support others schemes of extending of
+ secondary keys with components of the primary key we'll have
+ to change the type of this flag for an enumeration type.
+ */
+
+ for (i=0 ; i < keys ; i++, keyinfo++)
+ {
+ if (new_frm_ver >= 3)
+ {
+ if (strpos + 8 >= frm_image_end)
+ return 1;
+ keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
+ keyinfo->key_length= (uint) uint2korr(strpos+2);
+ keyinfo->user_defined_key_parts= (uint) strpos[4];
+ keyinfo->algorithm= (enum ha_key_alg) strpos[5];
+ keyinfo->block_size= uint2korr(strpos+6);
+ strpos+=8;
+ }
+ else
+ {
+ if (strpos + 4 >= frm_image_end)
+ return 1;
+ keyinfo->flags= ((uint) strpos[0]) ^ HA_NOSAME;
+ keyinfo->key_length= (uint) uint2korr(strpos+1);
+ keyinfo->user_defined_key_parts= (uint) strpos[3];
+ keyinfo->algorithm= HA_KEY_ALG_UNDEF;
+ strpos+=4;
+ }
+
+ if (i == 0)
+ {
+ ext_key_parts+= (share->use_ext_keys ? first_keyinfo->user_defined_key_parts*(keys-1) : 0);
+ n_length=keys * sizeof(KEY) + ext_key_parts * sizeof(KEY_PART_INFO);
+ if (!(keyinfo= (KEY*) alloc_root(&share->mem_root,
+ n_length + len)))
+ return 1;
+ bzero((char*) keyinfo,n_length);
+ share->key_info= keyinfo;
+ key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo + keys);
+
+ if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
+ sizeof(ulong) * ext_key_parts)))
+ return 1;
+ first_key_part= key_part;
+ first_key_parts= first_keyinfo->user_defined_key_parts;
+ keyinfo->flags= first_keyinfo->flags;
+ keyinfo->key_length= first_keyinfo->key_length;
+ keyinfo->user_defined_key_parts= first_keyinfo->user_defined_key_parts;
+ keyinfo->algorithm= first_keyinfo->algorithm;
+ if (new_frm_ver >= 3)
+ keyinfo->block_size= first_keyinfo->block_size;
+ }
+
+ keyinfo->key_part= key_part;
+ keyinfo->rec_per_key= rec_per_key;
+ for (j=keyinfo->user_defined_key_parts ; j-- ; key_part++)
+ {
+ if (strpos + (new_frm_ver >= 1 ? 9 : 7) >= frm_image_end)
+ return 1;
+ *rec_per_key++=0;
+ key_part->fieldnr= (uint16) (uint2korr(strpos) & FIELD_NR_MASK);
+ key_part->offset= (uint) uint2korr(strpos+2)-1;
+ key_part->key_type= (uint) uint2korr(strpos+5);
+ // key_part->field= (Field*) 0; // Will be fixed later
+ if (new_frm_ver >= 1)
+ {
+ key_part->key_part_flag= *(strpos+4);
+ key_part->length= (uint) uint2korr(strpos+7);
+ strpos+=9;
+ }
+ else
+ {
+ key_part->length= *(strpos+4);
+ key_part->key_part_flag=0;
+ if (key_part->length > 128)
+ {
+ key_part->length&=127; /* purecov: inspected */
+ key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
+ }
+ strpos+=7;
+ }
+ key_part->store_length=key_part->length;
+ }
+
+ /*
+ Add primary key to end of extended keys for non unique keys for
+ storage engines that supports it.
+ */
+ keyinfo->ext_key_parts= keyinfo->user_defined_key_parts;
+ keyinfo->ext_key_flags= keyinfo->flags;
+ keyinfo->ext_key_part_map= 0;
+ if (share->use_ext_keys && i && !(keyinfo->flags & HA_NOSAME))
+ {
+ keyinfo->ext_key_part_map= 0;
+ for (j= 0;
+ j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS;
+ j++)
+ {
+ uint key_parts= keyinfo->user_defined_key_parts;
+ KEY_PART_INFO* curr_key_part= keyinfo->key_part;
+ KEY_PART_INFO* curr_key_part_end= curr_key_part+key_parts;
+ for ( ; curr_key_part < curr_key_part_end; curr_key_part++)
+ {
+ if (curr_key_part->fieldnr == first_key_part[j].fieldnr)
+ break;
+ }
+ if (curr_key_part == curr_key_part_end)
+ {
+ *key_part++= first_key_part[j];
+ *rec_per_key++= 0;
+ keyinfo->ext_key_parts++;
+ keyinfo->ext_key_part_map|= 1 << j;
+ }
+ }
+ if (j == first_key_parts)
+ keyinfo->ext_key_flags= keyinfo->flags | HA_EXT_NOSAME;
+ }
+ share->ext_key_parts+= keyinfo->ext_key_parts;
+ }
+ keynames=(char*) key_part;
+ strpos+= strnmov(keynames, (char *) strpos, frm_image_end - strpos) - keynames;
+ if (*strpos++) // key names are \0-terminated
+ return 1;
+
+ //reading index comments
+ for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
+ {
+ if (keyinfo->flags & HA_USES_COMMENT)
+ {
+ if (strpos + 2 >= frm_image_end)
+ return 1;
+ keyinfo->comment.length= uint2korr(strpos);
+ strpos+= 2;
+
+ if (strpos + keyinfo->comment.length >= frm_image_end)
+ return 1;
+ keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos,
+ keyinfo->comment.length);
+ strpos+= keyinfo->comment.length;
+ }
+ DBUG_ASSERT(test(keyinfo->flags & HA_USES_COMMENT) ==
+ (keyinfo->comment.length > 0));
+ }
+
+ share->keys= keys; // do it *after* all key_info's are initialized
+
+ return 0;
+}
+
/**
Read data from a binary .frm file image into a TABLE_SHARE
@@ -680,7 +858,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
uint db_create_options, keys, key_parts, n_length;
uint com_length, null_bit_pos;
uint extra_rec_buf_length;
- uint i,j;
+ uint i;
bool use_hash;
char *keynames, *names, *comment_pos;
const uchar *forminfo, *extra2;
@@ -688,7 +866,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
uchar *record, *null_flags, *null_pos;
const uchar *disk_buff, *strpos;
ulong pos, record_offset;
- ulong *rec_per_key= NULL;
ulong rec_buff_length;
handler *handler_file= 0;
KEY *keyinfo;
@@ -703,9 +880,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
const uchar *options= 0;
KEY first_keyinfo;
uint len;
- KEY_PART_INFO *first_key_part= NULL;
uint ext_key_parts= 0;
- uint first_key_parts= 0;
plugin_ref se_plugin= 0;
keyinfo= &first_keyinfo;
share->ext_key_parts= 0;
@@ -869,191 +1044,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (disk_buff[0] & 0x80)
{
- share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
+ keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
share->key_parts= key_parts= uint2korr(disk_buff+2);
}
else
{
- share->keys= keys= disk_buff[0];
+ keys= disk_buff[0];
share->key_parts= key_parts= disk_buff[1];
}
share->keys_for_keyread.init(0);
share->keys_in_use.init(keys);
-
- /*
- At this point we don't have enough information read from the frm file
- to get a proper handlerton for the interesting engine in order to get
- properties of this engine.
- */
- /* Currently only InnoDB can use extended keys */
- share->set_use_ext_keys_flag(legacy_db_type == DB_TYPE_INNODB);
+ ext_key_parts= key_parts;
len= (uint) uint2korr(disk_buff+4);
- if (!keys)
- {
- if (!(keyinfo = (KEY*) alloc_root(&share->mem_root, len)))
- goto err;
- bzero((char*) keyinfo, len);
- key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo+keys);
- }
- strpos= disk_buff+6;
-
- /*
- If share->use_ext_keys is set to TRUE we assume that any key
- can be extended by the components of the primary key whose
- definition is read first from the frm file.
- For each key only those fields of the assumed primary key are
- added that are not included in the proper key definition.
- If after all it turns out that there is no primary key the
- added components are removed from each key.
-
- When in the future we support others schemes of extending of
- secondary keys with components of the primary key we'll have
- to change the type of this flag for an enumeration type.
- */
-
- for (i=0 ; i < keys ; i++, keyinfo++)
- {
- if (new_frm_ver >= 3)
- {
- if (strpos + 8 >= frm_image_end)
- goto err;
- keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
- keyinfo->key_length= (uint) uint2korr(strpos+2);
- keyinfo->user_defined_key_parts= (uint) strpos[4];
- keyinfo->algorithm= (enum ha_key_alg) strpos[5];
- keyinfo->block_size= uint2korr(strpos+6);
- strpos+=8;
- }
- else
- {
- if (strpos + 4 >= frm_image_end)
- goto err;
- keyinfo->flags= ((uint) strpos[0]) ^ HA_NOSAME;
- keyinfo->key_length= (uint) uint2korr(strpos+1);
- keyinfo->user_defined_key_parts= (uint) strpos[3];
- keyinfo->algorithm= HA_KEY_ALG_UNDEF;
- strpos+=4;
- }
-
- if (i == 0)
- {
- ext_key_parts= key_parts +
- (share->use_ext_keys ? first_keyinfo.user_defined_key_parts*(keys-1) : 0);
-
- n_length=keys * sizeof(KEY) + ext_key_parts * sizeof(KEY_PART_INFO);
- if (!(keyinfo= (KEY*) alloc_root(&share->mem_root,
- n_length + len)))
- goto err; /* purecov: inspected */
- bzero((char*) keyinfo,n_length);
- share->key_info= keyinfo;
- key_part= reinterpret_cast<KEY_PART_INFO*> (keyinfo + keys);
-
- if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
- sizeof(ulong) * ext_key_parts)))
- goto err;
- first_key_part= key_part;
- first_key_parts= first_keyinfo.user_defined_key_parts;
- keyinfo->flags= first_keyinfo.flags;
- keyinfo->key_length= first_keyinfo.key_length;
- keyinfo->user_defined_key_parts= first_keyinfo.user_defined_key_parts;
- keyinfo->algorithm= first_keyinfo.algorithm;
- if (new_frm_ver >= 3)
- keyinfo->block_size= first_keyinfo.block_size;
- }
-
- keyinfo->key_part= key_part;
- keyinfo->rec_per_key= rec_per_key;
- for (j=keyinfo->user_defined_key_parts ; j-- ; key_part++)
- {
- if (strpos + (new_frm_ver >= 1 ? 9 : 7) >= frm_image_end)
- goto err;
- *rec_per_key++=0;
- key_part->fieldnr= (uint16) (uint2korr(strpos) & FIELD_NR_MASK);
- key_part->offset= (uint) uint2korr(strpos+2)-1;
- key_part->key_type= (uint) uint2korr(strpos+5);
- // key_part->field= (Field*) 0; // Will be fixed later
- if (new_frm_ver >= 1)
- {
- key_part->key_part_flag= *(strpos+4);
- key_part->length= (uint) uint2korr(strpos+7);
- strpos+=9;
- }
- else
- {
- key_part->length= *(strpos+4);
- key_part->key_part_flag=0;
- if (key_part->length > 128)
- {
- key_part->length&=127; /* purecov: inspected */
- key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */
- }
- strpos+=7;
- }
- key_part->store_length=key_part->length;
- }
- /*
- Add primary key to end of extended keys for non unique keys for
- storage engines that supports it.
- */
- keyinfo->ext_key_parts= keyinfo->user_defined_key_parts;
- keyinfo->ext_key_flags= keyinfo->flags;
- keyinfo->ext_key_part_map= 0;
- if (share->use_ext_keys && i && !(keyinfo->flags & HA_NOSAME))
- {
- keyinfo->ext_key_part_map= 0;
- for (j= 0;
- j < first_key_parts && keyinfo->ext_key_parts < MAX_REF_PARTS;
- j++)
- {
- uint key_parts= keyinfo->user_defined_key_parts;
- KEY_PART_INFO* curr_key_part= keyinfo->key_part;
- KEY_PART_INFO* curr_key_part_end= curr_key_part+key_parts;
- for ( ; curr_key_part < curr_key_part_end; curr_key_part++)
- {
- if (curr_key_part->fieldnr == first_key_part[j].fieldnr)
- break;
- }
- if (curr_key_part == curr_key_part_end)
- {
- *key_part++= first_key_part[j];
- *rec_per_key++= 0;
- keyinfo->ext_key_parts++;
- keyinfo->ext_key_part_map|= 1 << j;
- }
- }
- if (j == first_key_parts)
- keyinfo->ext_key_flags= keyinfo->flags | HA_EXT_NOSAME;
- }
- share->ext_key_parts+= keyinfo->ext_key_parts;
- }
- keynames=(char*) key_part;
- strpos+= strnmov(keynames, (char *) strpos, frm_image_end - strpos) - keynames;
- if (*strpos++) // key names are \0-terminated
- goto err;
-
- //reading index comments
- for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
- {
- if (keyinfo->flags & HA_USES_COMMENT)
- {
- if (strpos + 2 >= frm_image_end)
- goto err;
- keyinfo->comment.length= uint2korr(strpos);
- strpos+= 2;
-
- if (strpos + keyinfo->comment.length >= frm_image_end)
- goto err;
- keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos,
- keyinfo->comment.length);
- strpos+= keyinfo->comment.length;
- }
- DBUG_ASSERT(test(keyinfo->flags & HA_USES_COMMENT) ==
- (keyinfo->comment.length > 0));
- }
-
- share->reclength = uint2korr((frm_image+16));
+ share->reclength = uint2korr(frm_image+16);
share->stored_rec_length= share->reclength;
if (frm_image[26] == 1)
share->system= 1; /* one-record-database */
@@ -1098,7 +1103,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (se_plugin)
{
/* bad file, legacy_db_type did not match the name */
- goto err;
+ sql_print_warning("%s.frm is inconsistent: engine typecode %d, engine name %s (%d)",
+ share->normalized_path.str, legacy_db_type,
+ plugin_name(tmp_plugin)->str,
+ ha_legacy_type(plugin_data(tmp_plugin, handlerton *)));
}
/*
tmp_plugin is locked with a local lock.
@@ -1139,6 +1147,14 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
next_chunk+= str_db_type_length + 2;
}
+
+ share->set_use_ext_keys_flag(plugin_hton(se_plugin)->flags & HTON_EXTENDED_KEYS);
+
+ if (create_key_infos(disk_buff + 6, frm_image_end, keys, keyinfo,
+ new_frm_ver, ext_key_parts,
+ share, len, &first_keyinfo, keynames))
+ goto err;
+
if (next_chunk + 5 < buff_end)
{
uint32 partition_info_str_len = uint4korr(next_chunk);
@@ -1225,6 +1241,14 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
DBUG_ASSERT(next_chunk <= buff_end);
}
+ else
+ {
+ if (create_key_infos(disk_buff + 6, frm_image_end, keys, keyinfo,
+ new_frm_ver, ext_key_parts,
+ share, len, &first_keyinfo, keynames))
+ goto err;
+ }
+
share->key_block_size= uint2korr(frm_image+62);
if (share->db_plugin && !plugin_equals(share->db_plugin, se_plugin))
@@ -1260,7 +1284,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
share->comment.length);
}
- DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length, vcol_screen_length));
+ DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, keys,n_length,int_length, com_length, vcol_screen_length));
if (!(field_ptr = (Field **)
@@ -1614,12 +1638,12 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
else
{
- add_first_key_parts= first_key_parts;
+ add_first_key_parts= first_keyinfo.user_defined_key_parts;
/*
Do not add components of the primary key starting from
the major component defined over the beginning of a field.
*/
- for (i= 0; i < first_key_parts; i++)
+ for (i= 0; i < first_keyinfo.user_defined_key_parts; i++)
{
uint fieldnr= keyinfo[0].key_part[i].fieldnr;
if (share->field[fieldnr-1]->key_length() !=
@@ -1632,7 +1656,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
}
- for (uint key=0 ; key < share->keys ; key++,keyinfo++)
+ for (uint key=0 ; key < keys ; key++,keyinfo++)
{
uint usable_parts= 0;
keyinfo->name=(char*) share->keynames.type_names[key];
@@ -1902,7 +1926,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
{
reg_field= *share->found_next_number_field;
if ((int) (share->next_number_index= (uint)
- find_ref_key(share->key_info, share->keys,
+ find_ref_key(share->key_info, keys,
share->default_values, reg_field,
&share->next_number_key_offset,
&share->next_number_keypart)) < 0)
@@ -2191,7 +2215,7 @@ bool fix_vcol_expr(THD *thd,
Item* func_expr= vcol_info->expr_item;
bool result= TRUE;
TABLE_LIST tables;
- int error;
+ int error= 0;
const char *save_where;
Field **ptr, *field;
enum_mark_columns save_mark_used_columns= thd->mark_used_columns;
@@ -2204,7 +2228,11 @@ bool fix_vcol_expr(THD *thd,
thd->where= "virtual column function";
/* Fix fields referenced to by the virtual column function */
- error= func_expr->fix_fields(thd, (Item**)0);
+ if (!func_expr->fixed)
+ error= func_expr->fix_fields(thd, &vcol_info->expr_item);
+ /* fix_fields could change the expression */
+ func_expr= vcol_info->expr_item;
+ /* Number of columns will be checked later */
if (unlikely(error))
{