summaryrefslogtreecommitdiff
path: root/sql/field.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/field.cc')
-rw-r--r--sql/field.cc477
1 files changed, 330 insertions, 147 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 73caddf1d0b..c06b7006a2b 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -429,8 +429,7 @@ uint Field::fill_cache_field(CACHE_FIELD *copy)
copy->length-=table->blob_ptr_size;
return copy->length;
}
- else if (!zero_pack() && (type() == FIELD_TYPE_STRING && copy->length > 4 ||
- type() == FIELD_TYPE_VAR_STRING))
+ else if (!zero_pack() && (type() == FIELD_TYPE_STRING && copy->length >= 4))
copy->strip=1; /* Remove end space */
else
copy->strip=0;
@@ -479,6 +478,26 @@ bool Field::optimize_range(uint idx, uint part)
return test(table->file->index_flags(idx, part, 1) & HA_READ_RANGE);
}
+
+Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table)
+{
+ Field *tmp;
+ if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of())))
+ return 0;
+
+ if (tmp->table->maybe_null)
+ tmp->flags&= ~NOT_NULL_FLAG;
+ tmp->table= new_table;
+ tmp->key_start.init(0);
+ tmp->part_of_key.init(0);
+ tmp->part_of_sortkey.init(0);
+ tmp->unireg_check=Field::NONE;
+ tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
+ ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+ tmp->reset_fields();
+ return tmp;
+}
+
/****************************************************************************
Field_null, a field that always return NULL
****************************************************************************/
@@ -4432,7 +4451,7 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr)
return field_charset->coll->strnncollsp(field_charset,
(const uchar*) a_ptr, field_length,
(const uchar*) b_ptr,
- field_length);
+ field_length, 0);
}
if (field_charset->mbmaxlen != 1)
{
@@ -4461,20 +4480,22 @@ void Field_string::sql_type(String &res) const
{
THD *thd= table->in_use;
CHARSET_INFO *cs=res.charset();
- ulong length= cs->cset->snprintf(cs,(char*) res.ptr(),
- res.alloced_length(), "%s(%d)",
- (field_length > 3 &&
- (table->db_options_in_use &
- HA_OPTION_PACK_RECORD) ?
- (has_charset() ? "varchar" : "varbinary") :
+ ulong length;
+
+ length= cs->cset->snprintf(cs,(char*) res.ptr(),
+ res.alloced_length(), "%s(%d)",
+ ((type() == MYSQL_TYPE_VAR_STRING &&
+ !thd->variables.new_mode) ?
+ (has_charset() ? "varchar" : "varbinary") :
(has_charset() ? "char" : "binary")),
- (int) field_length / charset()->mbmaxlen);
+ (int) field_length / charset()->mbmaxlen);
res.length(length);
if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
has_charset() && (charset()->state & MY_CS_BINSORT))
res.append(" binary");
}
+
char *Field_string::pack(char *to, const char *from, uint max_length)
{
uint length= min(field_length,max_length);
@@ -4508,10 +4529,27 @@ const char *Field_string::unpack(char *to, const char *from)
}
-int Field_string::pack_cmp(const char *a, const char *b, uint length)
+/*
+ Compare two packed keys
+
+ SYNOPSIS
+ pack_cmp()
+ a New key
+ b Original key
+ length Key length
+ insert_or_update 1 if this is an insert or update
+
+ RETURN
+ < 0 a < b
+ 0 a = b
+ > 0 a > b
+*/
+
+int Field_string::pack_cmp(const char *a, const char *b, uint length,
+ my_bool insert_or_update)
{
uint a_length, b_length;
- if (field_length > 255)
+ if (length > 255)
{
a_length= uint2korr(a);
b_length= uint2korr(b);
@@ -4523,29 +4561,51 @@ int Field_string::pack_cmp(const char *a, const char *b, uint length)
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- return my_strnncoll(field_charset,
- (const uchar*)a,a_length,
- (const uchar*)b,b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
-int Field_string::pack_cmp(const char *b, uint length)
+/*
+ Compare a packed key against row
+
+ SYNOPSIS
+ pack_cmp()
+ key Original key
+ length Key length. (May be less than field length)
+ insert_or_update 1 if this is an insert or update
+
+ RETURN
+ < 0 row < key
+ 0 row = key
+ > 0 row > key
+*/
+
+int Field_string::pack_cmp(const char *key, uint length,
+ my_bool insert_or_update)
{
- uint b_length;
- if (field_length > 255)
+ uint row_length, key_length;
+ char *end;
+ if (length > 255)
{
- b_length= uint2korr(b);
- b+= 2;
+ key_length= uint2korr(key);
+ key+= 2;
}
else
- b_length= (uint) (uchar) *b++;
- char *end= ptr + field_length;
+ key_length= (uint) (uchar) *key++;
+
+ /* Only use 'length' of key, not field_length */
+ end= ptr + length;
while (end > ptr && end[-1] == ' ')
end--;
- uint a_length = (uint) (end - ptr);
- return my_strnncoll(field_charset,
- (const uchar*)ptr,a_length,
- (const uchar*)b, b_length);
+ row_length= (uint) (end - ptr);
+
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) ptr, row_length,
+ (const uchar*) key, key_length,
+ insert_or_update);
}
@@ -4553,16 +4613,31 @@ uint Field_string::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+2;
- else
- return (uint) ((uchar) *data_ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
+
uint Field_string::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
}
+Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
+{
+ if (type() != MYSQL_TYPE_VAR_STRING || table == new_table)
+ return Field::new_field(root, new_table);
+
+ /*
+ Old VARCHAR field which should be modified to a VARCHAR on copy
+ This is done to ensure that ALTER TABLE will convert old VARCHAR fields
+ to now VARCHAR fields.
+ */
+ return new Field_varstring(field_length, maybe_null(),
+ field_name, new_table,
+ charset());
+}
+
/****************************************************************************
** VARCHAR type (Not available for the end user yet)
****************************************************************************/
@@ -4571,7 +4646,7 @@ uint Field_string::max_packed_col_length(uint max_length)
int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
int error= 0;
- uint32 not_used;
+ uint32 not_used, copy_length;
char buff[80];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
@@ -4585,15 +4660,21 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
if (conv_errors)
error= 1;
}
- if (length > field_length)
- {
- length=field_length;
+ /*
+ Make sure we don't break a multibyte sequence
+ as well as don't copy a malformed data.
+ */
+ copy_length= field_charset->cset->well_formed_len(field_charset,
+ from,from+length,
+ field_length/
+ field_charset->mbmaxlen);
+ memcpy(ptr + HA_KEY_BLOB_LENGTH, from, copy_length);
+ int2store(ptr, copy_length);
+
+ if (copy_length < length)
error= 1;
- }
if (error)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- memcpy(ptr+HA_KEY_BLOB_LENGTH,from,length);
- int2store(ptr, length);
return error;
}
@@ -4640,17 +4721,49 @@ int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
uint a_length=uint2korr(a_ptr);
uint b_length=uint2korr(b_ptr);
int diff;
- diff= my_strnncoll(field_charset,
- (const uchar*) a_ptr+HA_KEY_BLOB_LENGTH,
- min(a_length,b_length),
- (const uchar*) b_ptr+HA_KEY_BLOB_LENGTH,
- min(a_length,b_length));
- return diff ? diff : (int) (a_length - b_length);
+ diff= field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a_ptr+
+ HA_KEY_BLOB_LENGTH,
+ a_length,
+ (const uchar*) b_ptr+
+ HA_KEY_BLOB_LENGTH,
+ b_length,0);
+ return diff;
+}
+
+
+int Field_varstring::key_cmp(const byte *key_ptr, uint max_key_length)
+{
+ char *blob1;
+ uint length= uint2korr(ptr);
+ CHARSET_INFO *cs= charset();
+ uint char_length= max_key_length / cs->mbmaxlen;
+
+ char_length= my_charpos(cs, ptr + HA_KEY_BLOB_LENGTH,
+ ptr + HA_KEY_BLOB_LENGTH + length, char_length);
+ set_if_smaller(length, char_length);
+ return cs->coll->strnncollsp(cs,
+ (const uchar*) ptr+2, length,
+ (const uchar*) key_ptr+HA_KEY_BLOB_LENGTH,
+ uint2korr(key_ptr), 0);
}
+
+int Field_varstring::key_cmp(const byte *a,const byte *b)
+{
+ CHARSET_INFO *cs= charset();
+ return cs->coll->strnncollsp(cs,
+ (const uchar*) a + HA_KEY_BLOB_LENGTH,
+ uint2korr(a),
+ (const uchar*) b + HA_KEY_BLOB_LENGTH,
+ uint2korr(b),
+ 0);
+}
+
+
void Field_varstring::sort_string(char *to,uint length)
{
- uint tot_length=uint2korr(ptr);
+ uint tot_length= uint2korr(ptr);
tot_length= my_strnxfrm(field_charset,
(uchar*) to, length,
(uchar*) ptr+HA_KEY_BLOB_LENGTH,
@@ -4670,9 +4783,11 @@ void Field_varstring::sql_type(String &res) const
res.length(length);
}
+
char *Field_varstring::pack(char *to, const char *from, uint max_length)
{
uint length=uint2korr(from);
+ set_if_smaller(max_length, field_length);
if (length > max_length)
length=max_length;
*to++= (char) (length & 255);
@@ -4687,12 +4802,14 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length)
char *Field_varstring::pack_key(char *to, const char *from, uint max_length)
{
uint length=uint2korr(from);
- uint char_length= (field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length;
- from+=HA_KEY_BLOB_LENGTH;
+ uint char_length= ((field_charset->mbmaxlen > 1) ?
+ max_length/field_charset->mbmaxlen : max_length);
+ from+= HA_KEY_BLOB_LENGTH;
if (length > char_length)
+ {
char_length= my_charpos(field_charset, from, from+length, char_length);
- set_if_smaller(length, char_length);
+ set_if_smaller(length, char_length);
+ }
*to++= (char) (length & 255);
if (max_length > 255)
*to++= (char) (length >> 8);
@@ -4705,16 +4822,16 @@ char *Field_varstring::pack_key(char *to, const char *from, uint max_length)
const char *Field_varstring::unpack(char *to, const char *from)
{
uint length;
- if (field_length > 255)
+ if (field_length <= 255)
{
length= (uint) (uchar) (*to= *from++);
to[1]=0;
}
else
{
- length=uint2korr(from);
- to[0] = *from++;
- to[1] = *from++;
+ length= uint2korr(from);
+ to[0]= *from++;
+ to[1]= *from++;
}
if (length)
memcpy(to+HA_KEY_BLOB_LENGTH, from, length);
@@ -4722,77 +4839,122 @@ const char *Field_varstring::unpack(char *to, const char *from)
}
-int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
+int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length,
+ my_bool insert_or_update)
{
uint a_length;
uint b_length;
if (key_length > 255)
{
- a_length=uint2korr(a); a+= 2;
- b_length=uint2korr(b); b+= 2;
+ a_length=uint2korr(a); a+= HA_KEY_BLOB_LENGTH;
+ b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
}
else
{
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
-int Field_varstring::pack_cmp(const char *b, uint key_length)
+
+int Field_varstring::pack_cmp(const char *b, uint key_length,
+ my_bool insert_or_update)
{
char *a= ptr+HA_KEY_BLOB_LENGTH;
uint a_length= uint2korr(ptr);
uint b_length;
+ uint char_length= ((field_charset->mbmaxlen > 1) ?
+ key_length / field_charset->mbmaxlen : key_length);
+
if (key_length > 255)
{
- b_length=uint2korr(b); b+= 2;
+ b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
}
else
- {
b_length= (uint) (uchar) *b++;
+
+ if (a_length > char_length)
+ {
+ char_length= my_charpos(field_charset, a, a+a_length, char_length);
+ set_if_smaller(a_length, char_length);
}
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a,
+ a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
+
uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+HA_KEY_BLOB_LENGTH;
- else
- return (uint) ((uchar) *data_ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
+
uint Field_varstring::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
}
-void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
- imagetype type)
+
+void Field_varstring::get_key_image(char *buff, uint length, imagetype type)
{
- uint f_length=uint2korr(ptr);
- if (f_length > length)
- f_length= length;
- int2store(buff,length);
- memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+HA_KEY_BLOB_LENGTH, length);
-#ifdef HAVE_purify
+ uint f_length= uint2korr(ptr);
+ uint char_length= length / field_charset->mbmaxlen;
+ char_length= my_charpos(field_charset, ptr, ptr + HA_KEY_BLOB_LENGTH,
+ char_length);
+ set_if_smaller(f_length, char_length);
+ int2store(buff,f_length);
+ memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+HA_KEY_BLOB_LENGTH, f_length);
if (f_length < length)
+ {
+ /*
+ Must clear this as we do a memcmp in opt_range.cc to detect
+ identical keys
+ */
bzero(buff+HA_KEY_BLOB_LENGTH+f_length, (length-f_length));
-#endif
+ }
}
-void Field_varstring::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+
+void Field_varstring::set_key_image(char *buff,uint length)
{
length=uint2korr(buff); // Real length is here
- (void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
+ (void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length,
+ field_charset);
}
+int Field_varstring::cmp_binary_offset(uint row_offset)
+{
+ return cmp_binary(ptr, ptr+row_offset);
+}
+
+
+int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr,
+ uint32 max_length)
+{
+ char *a,*b;
+ uint diff;
+ uint32 a_length,b_length;
+
+ a_length= uint2korr(a_ptr);
+ b_length= uint2korr(b_ptr);
+ set_if_smaller(a_length, max_length);
+ set_if_smaller(b_length, max_length);
+ if (a_length != b_length)
+ return 1;
+ return memcmp(a_ptr+2, b_ptr+2, a_length);
+}
+
/****************************************************************************
** blob type
@@ -5030,10 +5192,10 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
uint32 b_length)
{
- return field_charset->coll->strnncoll(field_charset,
- (const uchar*)a, a_length,
- (const uchar*)b, b_length,
- 0);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*)a, a_length,
+ (const uchar*)b, b_length,
+ 0);
}
@@ -5080,8 +5242,7 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
/* The following is used only when comparing a key */
-void Field_blob::get_key_image(char *buff,uint length,
- CHARSET_INFO *cs, imagetype type)
+void Field_blob::get_key_image(char *buff, uint length, imagetype type)
{
uint32 blob_length= get_length(ptr);
char *blob;
@@ -5116,8 +5277,9 @@ void Field_blob::get_key_image(char *buff,uint length,
#endif /*HAVE_SPATIAL*/
get_ptr(&blob);
- uint char_length= length / cs->mbmaxlen;
- char_length= my_charpos(cs, blob, blob + blob_length, char_length);
+ uint char_length= length / field_charset->mbmaxlen;
+ char_length= my_charpos(field_charset, blob, blob + blob_length,
+ char_length);
set_if_smaller(blob_length, char_length);
if ((uint32) length > blob_length)
@@ -5133,10 +5295,11 @@ void Field_blob::get_key_image(char *buff,uint length,
memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
}
-void Field_blob::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+
+void Field_blob::set_key_image(char *buff,uint length)
{
length= uint2korr(buff);
- (void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
+ (void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, field_charset);
}
@@ -5149,7 +5312,7 @@ int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
uint char_length= max_key_length / cs->mbmaxlen;
char_length= my_charpos(cs, blob1, blob1+blob_length, char_length);
set_if_smaller(blob_length, char_length);
- return Field_blob::cmp(blob1,min(blob_length, max_key_length),
+ return Field_blob::cmp(blob1, blob_length,
(char*) key_ptr+HA_KEY_BLOB_LENGTH,
uint2korr(key_ptr));
}
@@ -5241,7 +5404,8 @@ const char *Field_blob::unpack(char *to, const char *from)
/* Keys for blobs are like keys on varchars */
-int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
+int Field_blob::pack_cmp(const char *a, const char *b, uint key_length,
+ my_bool insert_or_update)
{
uint a_length;
uint b_length;
@@ -5255,13 +5419,15 @@ int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
-int Field_blob::pack_cmp(const char *b, uint key_length)
+int Field_blob::pack_cmp(const char *b, uint key_length,
+ my_bool insert_or_update)
{
char *a;
memcpy_fixed(&a,ptr+packlength,sizeof(char*));
@@ -5275,12 +5441,11 @@ int Field_blob::pack_cmp(const char *b, uint key_length)
b_length=uint2korr(b); b+=2;
}
else
- {
b_length= (uint) (uchar) *b++;
- }
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
/* Create a packed key that will be used for storage from a MySQL row */
@@ -5290,8 +5455,8 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
char *save=ptr;
ptr=(char*) from;
uint32 length=get_length(); // Length of from string
- uint char_length= (field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length;
+ uint char_length= ((field_charset->mbmaxlen > 1) ?
+ max_length/field_charset->mbmaxlen : max_length);
if (length)
get_ptr((char**) &from);
if (length > char_length)
@@ -5365,14 +5530,15 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
return to+length;
}
+
uint Field_blob::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+2;
- else
- return (uint) ((uchar) *data_ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
+
uint Field_blob::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
@@ -5381,8 +5547,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
#ifdef HAVE_SPATIAL
-void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
- imagetype type)
+void Field_geom::get_key_image(char *buff, uint length, imagetype type)
{
char *blob;
const char *dummy;
@@ -5411,11 +5576,6 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
}
-void Field_geom::set_key_image(char *buff, uint length, CHARSET_INFO *cs)
-{
- Field_blob::set_key_image(buff, length, cs);
-}
-
void Field_geom::sql_type(String &res) const
{
CHARSET_INFO *cs= &my_charset_latin1;
@@ -5864,7 +6024,7 @@ bool Field_num::eq_def(Field *field)
/*****************************************************************************
-** Handling of field and create_field
+ Handling of field and create_field
*****************************************************************************/
void create_field::create_length_to_internal_length(void)
@@ -5876,9 +6036,10 @@ void create_field::create_length_to_internal_length(void)
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VARCHAR:
length*= charset->mbmaxlen;
- pack_length= calc_pack_length(sql_type == FIELD_TYPE_VAR_STRING ?
- FIELD_TYPE_STRING : sql_type, length);
+ key_length*= charset->mbmaxlen;
+ pack_length= calc_pack_length(sql_type, length);
break;
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
@@ -5890,6 +6051,22 @@ void create_field::create_length_to_internal_length(void)
}
}
+
+enum_field_types get_blob_type_from_length(ulong length)
+{
+ enum_field_types type;
+ if (length < 256)
+ type= FIELD_TYPE_TINY_BLOB;
+ else if (length < 65536)
+ type= FIELD_TYPE_BLOB;
+ else if (length < 256L*256L*256L)
+ type= FIELD_TYPE_MEDIUM_BLOB;
+ else
+ type= FIELD_TYPE_LONG_BLOB;
+ return type;
+}
+
+
/*
Make a field from the .frm file info
*/
@@ -5897,9 +6074,10 @@ void create_field::create_length_to_internal_length(void)
uint32 calc_pack_length(enum_field_types type,uint32 length)
{
switch (type) {
+ case MYSQL_TYPE_VAR_STRING:
case FIELD_TYPE_STRING:
- case FIELD_TYPE_DECIMAL: return (length);
- case FIELD_TYPE_VAR_STRING: return (length+HA_KEY_BLOB_LENGTH);
+ case FIELD_TYPE_DECIMAL: return (length);
+ case MYSQL_TYPE_VARCHAR: return (length+HA_KEY_BLOB_LENGTH);
case FIELD_TYPE_YEAR:
case FIELD_TYPE_TINY : return 1;
case FIELD_TYPE_SHORT : return 2;
@@ -5972,12 +6150,16 @@ Field *make_field(char *ptr, uint32 field_length,
{
if (!f_is_packed(pack_flag))
{
- if (field_type == FIELD_TYPE_STRING ||
+ if (field_type == MYSQL_TYPE_STRING ||
field_type == FIELD_TYPE_DECIMAL || // 3.23 or 4.0 string
- field_type == FIELD_TYPE_VAR_STRING)
+ field_type == MYSQL_TYPE_VAR_STRING)
return new Field_string(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table,
field_charset);
+ if (field_type == MYSQL_TYPE_VARCHAR)
+ return new Field_varstring(ptr,field_length,null_pos,null_bit,
+ unireg_check, field_name, table,
+ field_charset);
return 0; // Error
}
@@ -6090,44 +6272,51 @@ create_field::create_field(Field *old_field,Field *orig_field)
flags= old_field->flags;
unireg_check=old_field->unireg_check;
pack_length=old_field->pack_length();
+ key_length= old_field->key_length();
sql_type= old_field->real_type();
charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
+ decimals= old_field->decimals();
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
pack_length= (pack_length- old_field->table->blob_ptr_size +
portable_sizeof_char_ptr);
- switch (sql_type)
- {
- case FIELD_TYPE_BLOB:
- switch (pack_length - portable_sizeof_char_ptr)
- {
- case 1: sql_type= FIELD_TYPE_TINY_BLOB; break;
- case 2: sql_type= FIELD_TYPE_BLOB; break;
- case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
- default: sql_type= FIELD_TYPE_LONG_BLOB; break;
- }
- length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; // QQ: Probably not needed
- break;
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
- length=(length+charset->mbmaxlen-1)/charset->mbmaxlen;
- break;
- default:
- break;
- }
-
- decimals= old_field->decimals();
- if (sql_type == FIELD_TYPE_STRING)
- {
+ switch (sql_type) {
+ case FIELD_TYPE_BLOB:
+ switch (pack_length - portable_sizeof_char_ptr) {
+ case 1: sql_type= FIELD_TYPE_TINY_BLOB; break;
+ case 2: sql_type= FIELD_TYPE_BLOB; break;
+ case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
+ default: sql_type= FIELD_TYPE_LONG_BLOB; break;
+ }
+ length=(length+charset->mbmaxlen-1) / charset->mbmaxlen;
+ key_length/= charset->mbmaxlen;
+ break;
+ case FIELD_TYPE_STRING:
/* Change CHAR -> VARCHAR if dynamic record length */
- sql_type=old_field->type();
- decimals=0;
+ if (old_field->type() == MYSQL_TYPE_VAR_STRING)
+ sql_type= MYSQL_TYPE_VARCHAR;
+ /* fall through */
+
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ /* These are corrected in create_length_to_internal_length */
+ length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
+ key_length/= charset->mbmaxlen;
+ break;
+#ifdef HAVE_SPATIAL
+ case FIELD_TYPE_GEOMETRY:
+ geom_type= ((Field_geom*)old_field)->geom_type;
+ break;
+#endif
+ default:
+ break;
}
+
if (flags & (ENUM_FLAG | SET_FLAG))
interval= ((Field_enum*) old_field)->typelib;
else
@@ -6152,12 +6341,6 @@ create_field::create_field(Field *old_field,Field *orig_field)
def= new Item_string(pos, tmp.length(), charset);
}
}
-#ifdef HAVE_SPATIAL
- if (sql_type == FIELD_TYPE_GEOMETRY)
- {
- geom_type= ((Field_geom*)old_field)->geom_type;
- }
-#endif
}