mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Cleanup/optimizations of structures and key usage to make it easier to move key-range-search to handler
This commit is contained in:
98
sql/field.cc
98
sql/field.cc
@ -4360,7 +4360,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
|
|||||||
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
|
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED);
|
||||||
error= 1;
|
error= 1;
|
||||||
}
|
}
|
||||||
memcpy(ptr+2,from,length);
|
memcpy(ptr+HA_KEY_BLOB_LENGTH,from,length);
|
||||||
int2store(ptr, length);
|
int2store(ptr, length);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -4389,18 +4389,18 @@ int Field_varstring::store(longlong nr)
|
|||||||
double Field_varstring::val_real(void)
|
double Field_varstring::val_real(void)
|
||||||
{
|
{
|
||||||
int not_used;
|
int not_used;
|
||||||
uint length=uint2korr(ptr)+2;
|
uint length=uint2korr(ptr)+HA_KEY_BLOB_LENGTH;
|
||||||
CHARSET_INFO *cs=charset();
|
CHARSET_INFO *cs=charset();
|
||||||
return my_strntod(cs,ptr+2,length,(char**)0, ¬_used);
|
return my_strntod(cs, ptr+HA_KEY_BLOB_LENGTH, length, (char**)0, ¬_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Field_varstring::val_int(void)
|
longlong Field_varstring::val_int(void)
|
||||||
{
|
{
|
||||||
int not_used;
|
int not_used;
|
||||||
uint length=uint2korr(ptr)+2;
|
uint length=uint2korr(ptr)+HA_KEY_BLOB_LENGTH;
|
||||||
CHARSET_INFO *cs=charset();
|
CHARSET_INFO *cs=charset();
|
||||||
return my_strntoll(cs,ptr+2,length,10,NULL, ¬_used);
|
return my_strntoll(cs,ptr+HA_KEY_BLOB_LENGTH,length,10,NULL, ¬_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4408,7 +4408,7 @@ String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
|
|||||||
String *val_ptr)
|
String *val_ptr)
|
||||||
{
|
{
|
||||||
uint length=uint2korr(ptr);
|
uint length=uint2korr(ptr);
|
||||||
val_ptr->set((const char*) ptr+2,length,field_charset);
|
val_ptr->set((const char*) ptr+HA_KEY_BLOB_LENGTH,length,field_charset);
|
||||||
return val_ptr;
|
return val_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4418,18 +4418,21 @@ int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
|
|||||||
uint a_length=uint2korr(a_ptr);
|
uint a_length=uint2korr(a_ptr);
|
||||||
uint b_length=uint2korr(b_ptr);
|
uint b_length=uint2korr(b_ptr);
|
||||||
int diff;
|
int diff;
|
||||||
diff=my_strnncoll(field_charset,
|
diff= my_strnncoll(field_charset,
|
||||||
(const uchar*)a_ptr+2,min(a_length,b_length),
|
(const uchar*) a_ptr+HA_KEY_BLOB_LENGTH,
|
||||||
(const uchar*)b_ptr+2,min(a_length,b_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);
|
return diff ? diff : (int) (a_length - b_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Field_varstring::sort_string(char *to,uint length)
|
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,
|
tot_length= my_strnxfrm(field_charset,
|
||||||
(unsigned char *) to, length,
|
(uchar*) to, length,
|
||||||
(unsigned char *)ptr+2, tot_length);
|
(uchar*) ptr+HA_KEY_BLOB_LENGTH,
|
||||||
|
tot_length);
|
||||||
if (tot_length < length)
|
if (tot_length < length)
|
||||||
field_charset->cset->fill(field_charset, to+tot_length,length-tot_length,
|
field_charset->cset->fill(field_charset, to+tot_length,length-tot_length,
|
||||||
binary() ? (char) 0 : ' ');
|
binary() ? (char) 0 : ' ');
|
||||||
@ -4454,7 +4457,7 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length)
|
|||||||
if (max_length > 255)
|
if (max_length > 255)
|
||||||
*to++= (char) (length >> 8);
|
*to++= (char) (length >> 8);
|
||||||
if (length)
|
if (length)
|
||||||
memcpy(to, from+2, length);
|
memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
|
||||||
return to+length;
|
return to+length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4474,7 +4477,7 @@ const char *Field_varstring::unpack(char *to, const char *from)
|
|||||||
to[1] = *from++;
|
to[1] = *from++;
|
||||||
}
|
}
|
||||||
if (length)
|
if (length)
|
||||||
memcpy(to+2, from, length);
|
memcpy(to+HA_KEY_BLOB_LENGTH, from, length);
|
||||||
return from+length;
|
return from+length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4485,8 +4488,8 @@ int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
|
|||||||
uint b_length;
|
uint b_length;
|
||||||
if (key_length > 255)
|
if (key_length > 255)
|
||||||
{
|
{
|
||||||
a_length=uint2korr(a); a+=2;
|
a_length=uint2korr(a); a+= 2;
|
||||||
b_length=uint2korr(b); b+=2;
|
b_length=uint2korr(b); b+= 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -4494,32 +4497,32 @@ int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
|
|||||||
b_length= (uint) (uchar) *b++;
|
b_length= (uint) (uchar) *b++;
|
||||||
}
|
}
|
||||||
return my_strnncoll(field_charset,
|
return my_strnncoll(field_charset,
|
||||||
(const uchar *)a,a_length,
|
(const uchar*) a, a_length,
|
||||||
(const uchar *)b,b_length);
|
(const uchar*) b, b_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Field_varstring::pack_cmp(const char *b, uint key_length)
|
int Field_varstring::pack_cmp(const char *b, uint key_length)
|
||||||
{
|
{
|
||||||
char *a=ptr+2;
|
char *a= ptr+HA_KEY_BLOB_LENGTH;
|
||||||
uint a_length=uint2korr(ptr);
|
uint a_length= uint2korr(ptr);
|
||||||
uint b_length;
|
uint b_length;
|
||||||
if (key_length > 255)
|
if (key_length > 255)
|
||||||
{
|
{
|
||||||
b_length=uint2korr(b); b+=2;
|
b_length=uint2korr(b); b+= 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b_length= (uint) (uchar) *b++;
|
b_length= (uint) (uchar) *b++;
|
||||||
}
|
}
|
||||||
return my_strnncoll(field_charset,
|
return my_strnncoll(field_charset,
|
||||||
(const uchar *)a,a_length,
|
(const uchar*) a, a_length,
|
||||||
(const uchar *)b,b_length);
|
(const uchar*) b, b_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
|
uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
|
||||||
{
|
{
|
||||||
if (length > 255)
|
if (length > 255)
|
||||||
return uint2korr(data_ptr)+2;
|
return uint2korr(data_ptr)+HA_KEY_BLOB_LENGTH;
|
||||||
else
|
else
|
||||||
return (uint) ((uchar) *data_ptr)+1;
|
return (uint) ((uchar) *data_ptr)+1;
|
||||||
}
|
}
|
||||||
@ -4532,22 +4535,21 @@ uint Field_varstring::max_packed_col_length(uint max_length)
|
|||||||
void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
|
void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
|
||||||
imagetype type)
|
imagetype type)
|
||||||
{
|
{
|
||||||
length-= HA_KEY_BLOB_LENGTH;
|
|
||||||
uint f_length=uint2korr(ptr);
|
uint f_length=uint2korr(ptr);
|
||||||
if (f_length > length)
|
if (f_length > length)
|
||||||
f_length= length;
|
f_length= length;
|
||||||
int2store(buff,length);
|
int2store(buff,length);
|
||||||
memcpy(buff+2,ptr+2,length);
|
memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+HA_KEY_BLOB_LENGTH, length);
|
||||||
#ifdef HAVE_purify
|
#ifdef HAVE_purify
|
||||||
if (f_length < length)
|
if (f_length < length)
|
||||||
bzero(buff+2+f_length, (length-f_length));
|
bzero(buff+HA_KEY_BLOB_LENGTH+f_length, (length-f_length));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Field_varstring::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
|
void Field_varstring::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
length=uint2korr(buff); // Real length is here
|
length=uint2korr(buff); // Real length is here
|
||||||
(void) Field_varstring::store(buff+2, length, cs);
|
(void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4800,7 +4802,6 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
|
|||||||
void Field_blob::get_key_image(char *buff,uint length,
|
void Field_blob::get_key_image(char *buff,uint length,
|
||||||
CHARSET_INFO *cs, imagetype type)
|
CHARSET_INFO *cs, imagetype type)
|
||||||
{
|
{
|
||||||
length-= HA_KEY_BLOB_LENGTH;
|
|
||||||
uint32 blob_length= get_length(ptr);
|
uint32 blob_length= get_length(ptr);
|
||||||
char *blob;
|
char *blob;
|
||||||
|
|
||||||
@ -4839,18 +4840,18 @@ void Field_blob::get_key_image(char *buff,uint length,
|
|||||||
Must clear this as we do a memcmp in opt_range.cc to detect
|
Must clear this as we do a memcmp in opt_range.cc to detect
|
||||||
identical keys
|
identical keys
|
||||||
*/
|
*/
|
||||||
bzero(buff+2+blob_length, (length-blob_length));
|
bzero(buff+HA_KEY_BLOB_LENGTH+blob_length, (length-blob_length));
|
||||||
length=(uint) blob_length;
|
length=(uint) blob_length;
|
||||||
}
|
}
|
||||||
int2store(buff,length);
|
int2store(buff,length);
|
||||||
get_ptr(&blob);
|
get_ptr(&blob);
|
||||||
memcpy(buff+2,blob,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, CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
length=uint2korr(buff);
|
length= uint2korr(buff);
|
||||||
(void) Field_blob::store(buff+2,length,cs);
|
(void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4858,16 +4859,16 @@ int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
|
|||||||
{
|
{
|
||||||
char *blob1;
|
char *blob1;
|
||||||
uint blob_length=get_length(ptr);
|
uint blob_length=get_length(ptr);
|
||||||
max_key_length-=2;
|
|
||||||
memcpy_fixed(&blob1,ptr+packlength,sizeof(char*));
|
memcpy_fixed(&blob1,ptr+packlength,sizeof(char*));
|
||||||
return Field_blob::cmp(blob1,min(blob_length, max_key_length),
|
return Field_blob::cmp(blob1,min(blob_length, max_key_length),
|
||||||
(char*) key_ptr+2,uint2korr(key_ptr));
|
(char*) key_ptr+HA_KEY_BLOB_LENGTH,
|
||||||
|
uint2korr(key_ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
int Field_blob::key_cmp(const byte *a,const byte *b)
|
int Field_blob::key_cmp(const byte *a,const byte *b)
|
||||||
{
|
{
|
||||||
return Field_blob::cmp((char*) a+2,uint2korr(a),
|
return Field_blob::cmp((char*) a+HA_KEY_BLOB_LENGTH, uint2korr(a),
|
||||||
(char*) b+2,uint2korr(b));
|
(char*) b+HA_KEY_BLOB_LENGTH, uint2korr(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4883,8 +4884,8 @@ void Field_blob::sort_string(char *to,uint length)
|
|||||||
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
|
memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
|
||||||
|
|
||||||
blob_length=my_strnxfrm(field_charset,
|
blob_length=my_strnxfrm(field_charset,
|
||||||
(unsigned char *)to, length,
|
(uchar*) to, length,
|
||||||
(unsigned char *)blob, blob_length);
|
(uchar*) blob, blob_length);
|
||||||
if (blob_length < length)
|
if (blob_length < length)
|
||||||
field_charset->cset->fill(field_charset, to+blob_length,
|
field_charset->cset->fill(field_charset, to+blob_length,
|
||||||
length-blob_length,
|
length-blob_length,
|
||||||
@ -4966,8 +4967,8 @@ int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
|
|||||||
b_length= (uint) (uchar) *b++;
|
b_length= (uint) (uchar) *b++;
|
||||||
}
|
}
|
||||||
return my_strnncoll(field_charset,
|
return my_strnncoll(field_charset,
|
||||||
(const uchar *)a,a_length,
|
(const uchar*) a, a_length,
|
||||||
(const uchar *)b,b_length);
|
(const uchar*) b, b_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4989,8 +4990,8 @@ int Field_blob::pack_cmp(const char *b, uint key_length)
|
|||||||
b_length= (uint) (uchar) *b++;
|
b_length= (uint) (uchar) *b++;
|
||||||
}
|
}
|
||||||
return my_strnncoll(field_charset,
|
return my_strnncoll(field_charset,
|
||||||
(const uchar *)a,a_length,
|
(const uchar*) a, a_length,
|
||||||
(const uchar *)b,b_length);
|
(const uchar*) b, b_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a packed key that will be used for storage from a MySQL row */
|
/* Create a packed key that will be used for storage from a MySQL row */
|
||||||
@ -5026,7 +5027,7 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
|
|||||||
if (max_length > 255)
|
if (max_length > 255)
|
||||||
*to++= (char) (length >> 8);
|
*to++= (char) (length >> 8);
|
||||||
if (length)
|
if (length)
|
||||||
memcpy(to, from+2, length);
|
memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
|
||||||
return to+length;
|
return to+length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5049,11 +5050,12 @@ uint Field_blob::max_packed_col_length(uint max_length)
|
|||||||
void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
|
void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
|
||||||
imagetype type)
|
imagetype type)
|
||||||
{
|
{
|
||||||
length-= HA_KEY_BLOB_LENGTH;
|
|
||||||
ulong blob_length= get_length(ptr);
|
|
||||||
char *blob;
|
char *blob;
|
||||||
const char *dummy;
|
const char *dummy;
|
||||||
MBR mbr;
|
MBR mbr;
|
||||||
|
ulong blob_length= get_length(ptr);
|
||||||
|
Geometry_buffer buffer;
|
||||||
|
Geometry *gobj;
|
||||||
|
|
||||||
if (blob_length < SRID_SIZE)
|
if (blob_length < SRID_SIZE)
|
||||||
{
|
{
|
||||||
@ -5061,8 +5063,6 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
get_ptr(&blob);
|
get_ptr(&blob);
|
||||||
Geometry_buffer buffer;
|
|
||||||
Geometry *gobj;
|
|
||||||
gobj= Geometry::create_from_wkb(&buffer,
|
gobj= Geometry::create_from_wkb(&buffer,
|
||||||
blob + SRID_SIZE, blob_length - SRID_SIZE);
|
blob + SRID_SIZE, blob_length - SRID_SIZE);
|
||||||
if (gobj->get_mbr(&mbr, &dummy))
|
if (gobj->get_mbr(&mbr, &dummy))
|
||||||
@ -5555,7 +5555,7 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case FIELD_TYPE_STRING:
|
case FIELD_TYPE_STRING:
|
||||||
case FIELD_TYPE_DECIMAL: return (length);
|
case FIELD_TYPE_DECIMAL: return (length);
|
||||||
case FIELD_TYPE_VAR_STRING: return (length+2);
|
case FIELD_TYPE_VAR_STRING: return (length+HA_KEY_BLOB_LENGTH);
|
||||||
case FIELD_TYPE_YEAR:
|
case FIELD_TYPE_YEAR:
|
||||||
case FIELD_TYPE_TINY : return 1;
|
case FIELD_TYPE_TINY : return 1;
|
||||||
case FIELD_TYPE_SHORT : return 2;
|
case FIELD_TYPE_SHORT : return 2;
|
||||||
|
@ -199,7 +199,8 @@ public:
|
|||||||
{ memcpy(buff,ptr,length); }
|
{ memcpy(buff,ptr,length); }
|
||||||
inline void set_image(char *buff,uint length, CHARSET_INFO *cs)
|
inline void set_image(char *buff,uint length, CHARSET_INFO *cs)
|
||||||
{ memcpy(ptr,buff,length); }
|
{ memcpy(ptr,buff,length); }
|
||||||
virtual void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type)
|
virtual void get_key_image(char *buff,uint length, CHARSET_INFO *cs,
|
||||||
|
imagetype type)
|
||||||
{ get_image(buff,length,cs); }
|
{ get_image(buff,length,cs); }
|
||||||
virtual void set_key_image(char *buff,uint length, CHARSET_INFO *cs)
|
virtual void set_key_image(char *buff,uint length, CHARSET_INFO *cs)
|
||||||
{ set_image(buff,length,cs); }
|
{ set_image(buff,length,cs); }
|
||||||
|
152
sql/opt_range.cc
152
sql/opt_range.cc
@ -177,11 +177,11 @@ public:
|
|||||||
if (maybe_null && *min_value)
|
if (maybe_null && *min_value)
|
||||||
{
|
{
|
||||||
**min_key=1;
|
**min_key=1;
|
||||||
bzero(*min_key+1,length);
|
bzero(*min_key+1,length-1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy(*min_key,min_value,length+(int) maybe_null);
|
memcpy(*min_key,min_value,length);
|
||||||
(*min_key)+= length+(int) maybe_null;
|
(*min_key)+= length;
|
||||||
}
|
}
|
||||||
if (!(max_flag & NO_MAX_RANGE) &&
|
if (!(max_flag & NO_MAX_RANGE) &&
|
||||||
!(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
|
!(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
|
||||||
@ -189,18 +189,18 @@ public:
|
|||||||
if (maybe_null && *max_value)
|
if (maybe_null && *max_value)
|
||||||
{
|
{
|
||||||
**max_key=1;
|
**max_key=1;
|
||||||
bzero(*max_key+1,length);
|
bzero(*max_key+1,length-1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy(*max_key,max_value,length+(int) maybe_null);
|
memcpy(*max_key,max_value,length);
|
||||||
(*max_key)+= length+(int) maybe_null;
|
(*max_key)+= length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
|
void store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
|
||||||
{
|
{
|
||||||
SEL_ARG *key_tree= first();
|
SEL_ARG *key_tree= first();
|
||||||
key_tree->store(key[key_tree->part].part_length,
|
key_tree->store(key[key_tree->part].store_length,
|
||||||
range_key,*range_key_flag,range_key,NO_MAX_RANGE);
|
range_key,*range_key_flag,range_key,NO_MAX_RANGE);
|
||||||
*range_key_flag|= key_tree->min_flag;
|
*range_key_flag|= key_tree->min_flag;
|
||||||
if (key_tree->next_key_part &&
|
if (key_tree->next_key_part &&
|
||||||
@ -213,7 +213,7 @@ public:
|
|||||||
void store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
|
void store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
|
||||||
{
|
{
|
||||||
SEL_ARG *key_tree= last();
|
SEL_ARG *key_tree= last();
|
||||||
key_tree->store(key[key_tree->part].part_length,
|
key_tree->store(key[key_tree->part].store_length,
|
||||||
range_key, NO_MIN_RANGE, range_key,*range_key_flag);
|
range_key, NO_MIN_RANGE, range_key,*range_key_flag);
|
||||||
(*range_key_flag)|= key_tree->max_flag;
|
(*range_key_flag)|= key_tree->max_flag;
|
||||||
if (key_tree->next_key_part &&
|
if (key_tree->next_key_part &&
|
||||||
@ -676,19 +676,21 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
|||||||
if (!keys_to_use.is_set(idx))
|
if (!keys_to_use.is_set(idx))
|
||||||
continue;
|
continue;
|
||||||
KEY *key_info= &head->key_info[idx];
|
KEY *key_info= &head->key_info[idx];
|
||||||
|
KEY_PART_INFO *key_part_info= key_info->key_part;
|
||||||
|
|
||||||
if (key_info->flags & HA_FULLTEXT)
|
if (key_info->flags & HA_FULLTEXT)
|
||||||
continue; // ToDo: ft-keys in non-ft ranges, if possible SerG
|
continue; // ToDo: ft-keys in non-ft ranges, if possible SerG
|
||||||
|
|
||||||
param.key[param.keys]=key_parts;
|
param.key[param.keys]=key_parts;
|
||||||
for (uint part=0 ; part < key_info->key_parts ; part++,key_parts++)
|
for (uint part=0 ; part < key_info->key_parts ;
|
||||||
|
part++, key_parts++, key_part_info++)
|
||||||
{
|
{
|
||||||
key_parts->key=param.keys;
|
key_parts->key= param.keys;
|
||||||
key_parts->part=part;
|
key_parts->part= part;
|
||||||
key_parts->part_length= key_info->key_part[part].length;
|
key_parts->length= key_part_info->length;
|
||||||
key_parts->field= key_info->key_part[part].field;
|
key_parts->store_length= key_part_info->store_length;
|
||||||
key_parts->null_bit= key_info->key_part[part].null_bit;
|
key_parts->field= key_part_info->field;
|
||||||
if (key_parts->field->type() == FIELD_TYPE_BLOB)
|
key_parts->null_bit= key_part_info->null_bit;
|
||||||
key_parts->part_length+=HA_KEY_BLOB_LENGTH;
|
|
||||||
key_parts->image_type =
|
key_parts->image_type =
|
||||||
(key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
|
(key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
|
||||||
}
|
}
|
||||||
@ -1043,18 +1045,26 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
|||||||
DBUG_RETURN(0); // Can only optimize strings
|
DBUG_RETURN(0); // Can only optimize strings
|
||||||
|
|
||||||
offset=maybe_null;
|
offset=maybe_null;
|
||||||
length=key_part->part_length;
|
length=key_part->store_length;
|
||||||
if (field->type() == FIELD_TYPE_BLOB)
|
|
||||||
|
if (length != key_part->length + maybe_null)
|
||||||
{
|
{
|
||||||
offset+=HA_KEY_BLOB_LENGTH;
|
/* key packed with length prefix */
|
||||||
field_length=key_part->part_length-HA_KEY_BLOB_LENGTH;
|
offset+= HA_KEY_BLOB_LENGTH;
|
||||||
|
field_length= length - HA_KEY_BLOB_LENGTH;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (length < field_length)
|
if (unlikely(length < field_length))
|
||||||
length=field_length; // Only if overlapping key
|
{
|
||||||
|
/*
|
||||||
|
This can only happen in a table created with UNIREG where one key
|
||||||
|
overlaps many fields
|
||||||
|
*/
|
||||||
|
length= field_length;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
field_length=length;
|
field_length= length;
|
||||||
}
|
}
|
||||||
length+=offset;
|
length+=offset;
|
||||||
if (!(min_str= (char*) alloc_root(param->mem_root, length*2)))
|
if (!(min_str= (char*) alloc_root(param->mem_root, length*2)))
|
||||||
@ -1067,7 +1077,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
|||||||
res->ptr(), res->length(),
|
res->ptr(), res->length(),
|
||||||
((Item_func_like*)(param->cond))->escape,
|
((Item_func_like*)(param->cond))->escape,
|
||||||
wild_one, wild_many,
|
wild_one, wild_many,
|
||||||
field_length,
|
field_length-maybe_null,
|
||||||
min_str+offset, max_str+offset,
|
min_str+offset, max_str+offset,
|
||||||
&min_length, &max_length);
|
&min_length, &max_length);
|
||||||
if (like_error) // Can't optimize with LIKE
|
if (like_error) // Can't optimize with LIKE
|
||||||
@ -1105,13 +1115,13 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
|||||||
if (field->key_type() == HA_KEYTYPE_VARTEXT)
|
if (field->key_type() == HA_KEYTYPE_VARTEXT)
|
||||||
copies= 2;
|
copies= 2;
|
||||||
str= str2= (char*) alloc_root(param->mem_root,
|
str= str2= (char*) alloc_root(param->mem_root,
|
||||||
(key_part->part_length+maybe_null)*copies+1);
|
(key_part->store_length)*copies+1);
|
||||||
if (!str)
|
if (!str)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
if (maybe_null)
|
if (maybe_null)
|
||||||
*str= (char) field->is_real_null(); // Set to 1 if null
|
*str= (char) field->is_real_null(); // Set to 1 if null
|
||||||
field->get_key_image(str+maybe_null,key_part->part_length,
|
field->get_key_image(str+maybe_null, key_part->length,
|
||||||
field->charset(),key_part->image_type);
|
field->charset(), key_part->image_type);
|
||||||
if (copies == 2)
|
if (copies == 2)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1120,16 +1130,17 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
|
|||||||
all rows between 'X' and 'X ...'
|
all rows between 'X' and 'X ...'
|
||||||
*/
|
*/
|
||||||
uint length= uint2korr(str+maybe_null);
|
uint length= uint2korr(str+maybe_null);
|
||||||
str2= str+ key_part->part_length + maybe_null;
|
str2= str+ key_part->store_length;
|
||||||
/* remove end space */
|
/* remove end space */
|
||||||
while (length > 0 && str[length+HA_KEY_BLOB_LENGTH+maybe_null-1] == ' ')
|
while (length > 0 && str[length+HA_KEY_BLOB_LENGTH+maybe_null-1] == ' ')
|
||||||
length--;
|
length--;
|
||||||
int2store(str+maybe_null, length);
|
int2store(str+maybe_null, length);
|
||||||
/* Create key that is space filled */
|
/* Create key that is space filled */
|
||||||
memcpy(str2, str, length + HA_KEY_BLOB_LENGTH + maybe_null);
|
memcpy(str2, str, length + HA_KEY_BLOB_LENGTH + maybe_null);
|
||||||
bfill(str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null,
|
my_fill_8bit(field->charset(),
|
||||||
key_part->part_length-length - HA_KEY_BLOB_LENGTH, ' ');
|
str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null,
|
||||||
int2store(str2+maybe_null, key_part->part_length - HA_KEY_BLOB_LENGTH);
|
key_part->length-length, ' ');
|
||||||
|
int2store(str2+maybe_null, key_part->length);
|
||||||
}
|
}
|
||||||
if (!(tree=new SEL_ARG(field,str,str2)))
|
if (!(tree=new SEL_ARG(field,str,str2)))
|
||||||
DBUG_RETURN(0); // out of memory
|
DBUG_RETURN(0); // out of memory
|
||||||
@ -2236,7 +2247,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
|
|||||||
uint tmp_min_flag,tmp_max_flag,keynr;
|
uint tmp_min_flag,tmp_max_flag,keynr;
|
||||||
char *tmp_min_key=min_key,*tmp_max_key=max_key;
|
char *tmp_min_key=min_key,*tmp_max_key=max_key;
|
||||||
|
|
||||||
key_tree->store(param->key[idx][key_tree->part].part_length,
|
key_tree->store(param->key[idx][key_tree->part].store_length,
|
||||||
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
|
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
|
||||||
uint min_key_length= (uint) (tmp_min_key- param->min_key);
|
uint min_key_length= (uint) (tmp_min_key- param->min_key);
|
||||||
uint max_key_length= (uint) (tmp_max_key- param->max_key);
|
uint max_key_length= (uint) (tmp_max_key- param->max_key);
|
||||||
@ -2373,7 +2384,7 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
char *tmp_min_key=min_key,*tmp_max_key=max_key;
|
char *tmp_min_key=min_key,*tmp_max_key=max_key;
|
||||||
key_tree->store(key[key_tree->part].part_length,
|
key_tree->store(key[key_tree->part].store_length,
|
||||||
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
|
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
|
||||||
|
|
||||||
if (key_tree->next_key_part &&
|
if (key_tree->next_key_part &&
|
||||||
@ -2491,13 +2502,10 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
|
|||||||
{
|
{
|
||||||
for (const char *end=key+length ;
|
for (const char *end=key+length ;
|
||||||
key < end;
|
key < end;
|
||||||
key+= key_part++->part_length)
|
key+= key_part++->store_length)
|
||||||
{
|
{
|
||||||
if (key_part->null_bit)
|
if (key_part->null_bit && *key)
|
||||||
{
|
return 1;
|
||||||
if (*key++)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2541,9 +2549,8 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
|
|||||||
{
|
{
|
||||||
key_part->part=part;
|
key_part->part=part;
|
||||||
key_part->field= key_info->key_part[part].field;
|
key_part->field= key_info->key_part[part].field;
|
||||||
key_part->part_length= key_info->key_part[part].length;
|
key_part->length= key_info->key_part[part].length;
|
||||||
if (key_part->field->type() == FIELD_TYPE_BLOB)
|
key_part->store_length= key_info->key_part[part].store_length;
|
||||||
key_part->part_length+=HA_KEY_BLOB_LENGTH;
|
|
||||||
key_part->null_bit= key_info->key_part[part].null_bit;
|
key_part->null_bit= key_info->key_part[part].null_bit;
|
||||||
}
|
}
|
||||||
if (quick->ranges.push_back(range))
|
if (quick->ranges.push_back(range))
|
||||||
@ -2668,14 +2675,16 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg)
|
|||||||
return 0; /* key can't be to large */
|
return 0; /* key can't be to large */
|
||||||
|
|
||||||
KEY_PART *key_part=key_parts;
|
KEY_PART *key_part=key_parts;
|
||||||
|
uint store_length;
|
||||||
for (char *key=range_arg->max_key, *end=key+range_arg->max_length;
|
for (char *key=range_arg->max_key, *end=key+range_arg->max_length;
|
||||||
key < end;
|
key < end;
|
||||||
key+= key_part++->part_length)
|
key+= store_length, key_part++)
|
||||||
{
|
{
|
||||||
int cmp;
|
int cmp;
|
||||||
|
store_length= key_part->store_length;
|
||||||
if (key_part->null_bit)
|
if (key_part->null_bit)
|
||||||
{
|
{
|
||||||
if (*key++)
|
if (*key)
|
||||||
{
|
{
|
||||||
if (!key_part->field->is_null())
|
if (!key_part->field->is_null())
|
||||||
return 1;
|
return 1;
|
||||||
@ -2683,13 +2692,15 @@ int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg)
|
|||||||
}
|
}
|
||||||
else if (key_part->field->is_null())
|
else if (key_part->field->is_null())
|
||||||
return 0;
|
return 0;
|
||||||
|
key++; // Skip null byte
|
||||||
|
store_length--;
|
||||||
}
|
}
|
||||||
if ((cmp=key_part->field->key_cmp((byte*) key, key_part->part_length)) < 0)
|
if ((cmp=key_part->field->key_cmp((byte*) key, key_part->length)) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (cmp > 0)
|
if (cmp > 0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match
|
return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2841,15 +2852,18 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
|
|||||||
return 0; /* key can't be to small */
|
return 0; /* key can't be to small */
|
||||||
|
|
||||||
KEY_PART *key_part = key_parts;
|
KEY_PART *key_part = key_parts;
|
||||||
|
uint store_length;
|
||||||
|
|
||||||
for (char *key = range_arg->min_key, *end = key + range_arg->min_length;
|
for (char *key = range_arg->min_key, *end = key + range_arg->min_length;
|
||||||
key < end;
|
key < end;
|
||||||
key += key_part++->part_length)
|
key += store_length, key_part++)
|
||||||
{
|
{
|
||||||
int cmp;
|
int cmp;
|
||||||
|
store_length= key_part->store_length;
|
||||||
if (key_part->null_bit)
|
if (key_part->null_bit)
|
||||||
{
|
{
|
||||||
// this key part allows null values; NULL is lower than everything else
|
// this key part allows null values; NULL is lower than everything else
|
||||||
if (*key++)
|
if (*key)
|
||||||
{
|
{
|
||||||
// the range is expecting a null value
|
// the range is expecting a null value
|
||||||
if (!key_part->field->is_null())
|
if (!key_part->field->is_null())
|
||||||
@ -2858,9 +2872,11 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
|
|||||||
}
|
}
|
||||||
else if (key_part->field->is_null())
|
else if (key_part->field->is_null())
|
||||||
return 1; // null -- outside the range
|
return 1; // null -- outside the range
|
||||||
|
key++;
|
||||||
|
store_length--;
|
||||||
}
|
}
|
||||||
if ((cmp = key_part->field->key_cmp((byte*) key,
|
if ((cmp = key_part->field->key_cmp((byte*) key,
|
||||||
key_part->part_length)) > 0)
|
key_part->length)) > 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
return 1;
|
return 1;
|
||||||
@ -2888,23 +2904,20 @@ bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg)
|
|||||||
bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
|
bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
|
||||||
uint used_key_parts)
|
uint used_key_parts)
|
||||||
{
|
{
|
||||||
uint offset,end;
|
uint offset, end;
|
||||||
KEY_PART *key_part = key_parts,
|
KEY_PART *key_part = key_parts,
|
||||||
*key_part_end= key_part+used_key_parts;
|
*key_part_end= key_part+used_key_parts;
|
||||||
|
|
||||||
for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ;
|
for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ;
|
||||||
offset < end && key_part != key_part_end ;
|
offset < end && key_part != key_part_end ;
|
||||||
offset += key_part++->part_length)
|
offset+= key_part++->store_length)
|
||||||
{
|
{
|
||||||
uint null_length=test(key_part->null_bit);
|
|
||||||
if (!memcmp((char*) range_arg->min_key+offset,
|
if (!memcmp((char*) range_arg->min_key+offset,
|
||||||
(char*) range_arg->max_key+offset,
|
(char*) range_arg->max_key+offset,
|
||||||
key_part->part_length + null_length))
|
key_part->store_length))
|
||||||
{
|
|
||||||
offset+=null_length;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (null_length && range_arg->min_key[offset])
|
if (key_part->null_bit && range_arg->min_key[offset])
|
||||||
return 1; // min_key is null and max_key isn't
|
return 1; // min_key is null and max_key isn't
|
||||||
// Range doesn't cover NULL. This is ok if there is no more null parts
|
// Range doesn't cover NULL. This is ok if there is no more null parts
|
||||||
break;
|
break;
|
||||||
@ -2946,33 +2959,34 @@ static void
|
|||||||
print_key(KEY_PART *key_part,const char *key,uint used_length)
|
print_key(KEY_PART *key_part,const char *key,uint used_length)
|
||||||
{
|
{
|
||||||
char buff[1024];
|
char buff[1024];
|
||||||
|
const char *key_end= key+used_length;
|
||||||
String tmp(buff,sizeof(buff),&my_charset_bin);
|
String tmp(buff,sizeof(buff),&my_charset_bin);
|
||||||
|
uint store_length;
|
||||||
|
|
||||||
for (uint length=0;
|
for (; key < key_end; key+=store_length, key_part++)
|
||||||
length < used_length ;
|
|
||||||
length+=key_part->part_length, key+=key_part->part_length, key_part++)
|
|
||||||
{
|
{
|
||||||
Field *field=key_part->field;
|
Field *field= key_part->field;
|
||||||
if (length != 0)
|
uint store_length= key_part->store_length;
|
||||||
fputc('/',DBUG_FILE);
|
|
||||||
if (field->real_maybe_null())
|
if (field->real_maybe_null())
|
||||||
{
|
{
|
||||||
length++; // null byte is not in part_length
|
if (*key)
|
||||||
if (*key++)
|
|
||||||
{
|
{
|
||||||
fwrite("NULL",sizeof(char),4,DBUG_FILE);
|
fwrite("NULL",sizeof(char),4,DBUG_FILE);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
key++;
|
||||||
|
store_length--;
|
||||||
}
|
}
|
||||||
field->set_key_image((char*) key,key_part->part_length -
|
field->set_key_image((char*) key, key_part->length, field->charset());
|
||||||
((field->type() == FIELD_TYPE_BLOB) ?
|
|
||||||
HA_KEY_BLOB_LENGTH : 0),
|
|
||||||
field->charset());
|
|
||||||
field->val_str(&tmp,&tmp);
|
field->val_str(&tmp,&tmp);
|
||||||
fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
|
fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
|
||||||
|
if (key+store_length < key_end)
|
||||||
|
fputc('/',DBUG_FILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void print_quick(QUICK_SELECT *quick,const key_map* needed_reg)
|
static void print_quick(QUICK_SELECT *quick,const key_map* needed_reg)
|
||||||
{
|
{
|
||||||
QUICK_RANGE *range;
|
QUICK_RANGE *range;
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
|
|
||||||
typedef struct st_key_part {
|
typedef struct st_key_part {
|
||||||
uint16 key,part,part_length;
|
uint16 key,part, store_length, length;
|
||||||
uint8 null_bit;
|
uint8 null_bit;
|
||||||
Field *field;
|
Field *field;
|
||||||
Field::imagetype image_type;
|
Field::imagetype image_type;
|
||||||
@ -68,7 +68,7 @@ class QUICK_RANGE :public Sql_alloc {
|
|||||||
|
|
||||||
class QUICK_SELECT {
|
class QUICK_SELECT {
|
||||||
public:
|
public:
|
||||||
bool next,dont_free;
|
bool next,dont_free,sorted;
|
||||||
int error;
|
int error;
|
||||||
uint index, max_used_key_length, used_key_parts;
|
uint index, max_used_key_length, used_key_parts;
|
||||||
TABLE *head;
|
TABLE *head;
|
||||||
|
@ -84,10 +84,10 @@ extern "C" void free_user_var(user_var_entry *entry)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
|
THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
|
||||||
no_table_fix_fields_cache(0),
|
|
||||||
last_insert_id_used(0),
|
last_insert_id_used(0),
|
||||||
insert_id_used(0), rand_used(0), in_lock_tables(0),
|
insert_id_used(0), rand_used(0), in_lock_tables(0),
|
||||||
global_read_lock(0), bootstrap(0)
|
global_read_lock(0), bootstrap(0),
|
||||||
|
no_table_fix_fields_cache(0)
|
||||||
{
|
{
|
||||||
host= user= priv_user= db= ip=0;
|
host= user= priv_user= db= ip=0;
|
||||||
host_or_ip= "connecting host";
|
host_or_ip= "connecting host";
|
||||||
|
@ -7152,6 +7152,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
|
|||||||
/* fall through */
|
/* fall through */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (select && select->quick)
|
||||||
|
select->quick->sorted= 1;
|
||||||
DBUG_RETURN(1); /* No need to sort */
|
DBUG_RETURN(1); /* No need to sort */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,7 +553,6 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
|
|||||||
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
|
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
|
||||||
}
|
}
|
||||||
if (field->type() == FIELD_TYPE_BLOB ||
|
if (field->type() == FIELD_TYPE_BLOB ||
|
||||||
field->type() == FIELD_TYPE_GEOMETRY ||
|
|
||||||
field->real_type() == FIELD_TYPE_VAR_STRING)
|
field->real_type() == FIELD_TYPE_VAR_STRING)
|
||||||
{
|
{
|
||||||
if (field->type() == FIELD_TYPE_BLOB)
|
if (field->type() == FIELD_TYPE_BLOB)
|
||||||
|
Reference in New Issue
Block a user