Commit 4b44b849 authored by unknown's avatar unknown

Fixed problem with range optimization over overlapping ranges (#2448)


mysql-test/r/ctype_tis620.result:
  Cleanup test
mysql-test/r/range.result:
  Test problem with range optimization over overlapping ranges (#2448)
mysql-test/t/ctype_tis620.test:
  Cleanup test
mysql-test/t/range.test:
  Test problem with range optimization over overlapping ranges (#2448)
sql/mysqld.cc:
  Remove debug statement
strings/ctype-tis620.c:
  est problem with range optimization over overlapping ranges (#2448)
parent 7ba7ce6e
DROP TABLE IF EXISTS t620;
CREATE TABLE t620 (
drop table if exists t1;
CREATE TABLE t1 (
recid int(11) NOT NULL auto_increment,
dyninfo text,
PRIMARY KEY (recid)
) TYPE=MyISAM;
INSERT INTO t620 VALUES (1,'color=\"STB,NPG\"\r\nengine=\"J30A13\"\r\nframe=\"MRHCG1640YP4\"\r\ngrade=\"V6\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CG164YEN\"\r\ntype=\"VT6\"\r\n');
INSERT INTO t620 VALUES (2,'color=\"HTM,NPG,DEG,RGS\"\r\nengine=\"F23A5YP1\"\r\nframe=\"MRHCF8640YP3\"\r\ngrade=\"EXi AT\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CF864YE\"\r\ntype=\"EXA\"\r\n');
) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1,'color=\"STB,NPG\"\r\nengine=\"J30A13\"\r\nframe=\"MRHCG1640YP4\"\r\ngrade=\"V6\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CG164YEN\"\r\ntype=\"VT6\"\r\n');
INSERT INTO t1 VALUES (2,'color=\"HTM,NPG,DEG,RGS\"\r\nengine=\"F23A5YP1\"\r\nframe=\"MRHCF8640YP3\"\r\ngrade=\"EXi AT\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CF864YE\"\r\ntype=\"EXA\"\r\n');
SELECT DISTINCT
(IF( LOCATE( 'year=\"', dyninfo ) = 1,
SUBSTRING( dyninfo, 6+1, LOCATE('\"\r',dyninfo) - 6 -1),
IF( LOCATE( '\nyear=\"', dyninfo ),
SUBSTRING( dyninfo, LOCATE( '\nyear=\"', dyninfo ) + 7,
LOCATE( '\"\r', SUBSTRING( dyninfo, LOCATE( '\nyear=\"', dyninfo ) +7 )) - 1), '' ))) AS year
FROM t620
FROM t1
HAVING year != '' ORDER BY year;
year
DROP TABLE t1;
......@@ -300,3 +300,16 @@ SELECT COUNT(*) FROM t1 WHERE (c=0 and b=1) or (c=0 and a=1);
COUNT(*)
6
DROP TABLE t1;
CREATE TABLE t1 ( a int not null, b int not null, INDEX ab(a,b) );
INSERT INTO t1 VALUES (47,1), (70,1), (15,1), (15, 4);
SELECT * FROM t1
WHERE
(
( b =1 AND a BETWEEN 14 AND 21 ) OR
( b =2 AND a BETWEEN 16 AND 18 ) OR
( b =3 AND a BETWEEN 15 AND 19 ) OR
(a BETWEEN 19 AND 47)
);
a b
15 1
47 1
DROP TABLE IF EXISTS t620;
CREATE TABLE t620 (
--disable_warnings
drop table if exists t1;
--enable_warnings
CREATE TABLE t1 (
recid int(11) NOT NULL auto_increment,
dyninfo text,
PRIMARY KEY (recid)
) TYPE=MyISAM;
) ENGINE=MyISAM;
INSERT INTO t620 VALUES (1,'color=\"STB,NPG\"\r\nengine=\"J30A13\"\r\nframe=\"MRHCG1640YP4\"\r\ngrade=\"V6\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CG164YEN\"\r\ntype=\"VT6\"\r\n');
INSERT INTO t620 VALUES (2,'color=\"HTM,NPG,DEG,RGS\"\r\nengine=\"F23A5YP1\"\r\nframe=\"MRHCF8640YP3\"\r\ngrade=\"EXi AT\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CF864YE\"\r\ntype=\"EXA\"\r\n');
INSERT INTO t1 VALUES (1,'color=\"STB,NPG\"\r\nengine=\"J30A13\"\r\nframe=\"MRHCG1640YP4\"\r\ngrade=\"V6\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CG164YEN\"\r\ntype=\"VT6\"\r\n');
INSERT INTO t1 VALUES (2,'color=\"HTM,NPG,DEG,RGS\"\r\nengine=\"F23A5YP1\"\r\nframe=\"MRHCF8640YP3\"\r\ngrade=\"EXi AT\"\r\nmodel=\"ACCORD\"\r\nmodelcode=\"CF864YE\"\r\ntype=\"EXA\"\r\n');
SELECT DISTINCT
(IF( LOCATE( 'year=\"', dyninfo ) = 1,
......@@ -14,5 +17,7 @@ SELECT DISTINCT
IF( LOCATE( '\nyear=\"', dyninfo ),
SUBSTRING( dyninfo, LOCATE( '\nyear=\"', dyninfo ) + 7,
LOCATE( '\"\r', SUBSTRING( dyninfo, LOCATE( '\nyear=\"', dyninfo ) +7 )) - 1), '' ))) AS year
FROM t620
FROM t1
HAVING year != '' ORDER BY year;
DROP TABLE t1;
......@@ -238,7 +238,7 @@ SELECT * FROM t1 WHERE a IN(1,2) AND b=5;
DROP TABLE t1;
#
# Test error with
# Test problem with range optimzer and sub ranges
#
CREATE TABLE t1 (a int, b int, c int, INDEX (c,a,b));
......@@ -249,3 +249,17 @@ SELECT COUNT(*) FROM t1 WHERE (c=0 and a=1) or (c=0 and b=1);
SELECT COUNT(*) FROM t1 WHERE (c=0 and b=1) or (c=0 and a=1);
DROP TABLE t1;
#
# Test problem with range optimization over overlapping ranges (#2448)
#
CREATE TABLE t1 ( a int not null, b int not null, INDEX ab(a,b) );
INSERT INTO t1 VALUES (47,1), (70,1), (15,1), (15, 4);
SELECT * FROM t1
WHERE
(
( b =1 AND a BETWEEN 14 AND 21 ) OR
( b =2 AND a BETWEEN 16 AND 18 ) OR
( b =3 AND a BETWEEN 15 AND 19 ) OR
(a BETWEEN 19 AND 47)
);
......@@ -4747,7 +4747,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
berkeley_env_flags|= DB_TXN_NOSYNC;
else
berkeley_env_flags&= ~DB_TXN_NOSYNC;
printf("berkeley_env_flags: %d, arg '%s'\n", berkeley_env_flags, argument);
break;
case OPT_BDB_NO_RECOVER:
berkeley_init_flags&= ~(DB_RECOVER);
......
......@@ -1710,6 +1710,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
return 0; // OOM
tmp->copy_max_to_min(&key);
tmp->increment_use_count(key1->use_count+1);
/* Increment key count as it may be used for next loop */
key.increment_use_count(1);
new_arg->next_key_part=key_or(tmp->next_key_part,key.next_key_part);
key1=key1->insert(new_arg);
break;
......@@ -2708,15 +2710,18 @@ int QUICK_SELECT_DESC::get_next()
}
else
{
/* Heikki changed Sept 11, 2002: since InnoDB does not store the cursor
position if READ_KEY_EXACT is used to a primary key with all
key columns specified, we must use below HA_READ_KEY_OR_NEXT,
so that InnoDB stores the cursor position and is able to move
the cursor one step backward after the search. */
/*
Heikki changed Sept 11, 2002: since InnoDB does not store the cursor
position if READ_KEY_EXACT is used to a primary key with all
key columns specified, we must use below HA_READ_KEY_OR_NEXT,
so that InnoDB stores the cursor position and is able to move
the cursor one step backward after the search. */
DBUG_ASSERT(range->flag & NEAR_MAX || range_reads_after_key(range));
/* Note: even if max_key is only a prefix, HA_READ_AFTER_KEY will
* do the right thing - go past all keys which match the prefix */
/*
Note: even if max_key is only a prefix, HA_READ_AFTER_KEY will
do the right thing - go past all keys which match the prefix
*/
result=file->index_read(record, (byte*) range->max_key,
range->max_length,
((range->flag & NEAR_MAX) ?
......
......@@ -449,225 +449,160 @@ uchar NEAR sort_order_tis620[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
};
/* Convert thai string to "Standard C String Function" sortable string
Arg: const source string and length of converted string
Ret: Sortable string
*/
static void _thai2sortable(uchar *tstr)
{
uchar *p ;
int len,tlen ;
uchar c,l2bias ;
tlen= len = strlen (tstr) ;
l2bias = 256 - 8 ;
for (p=tstr; tlen > 0; p++,tlen--)
{
c = *p ;
if (isthai(c))
{
int *t_ctype0 = t_ctype[c] ;
if (isconsnt(c))
l2bias -= 8 ;
if (isldvowel(c) && isconsnt(p[1]))
{
/*
simply swap between leading-vowel and consonant
*/
*p = p[1];
p[1]= c ;
tlen-- ;
p++;
continue ;
}
// if found level 2 char (L2_GARAN,L2_TONE*,L2_TYKHU) move to last
if (t_ctype0[1]>= L2_GARAN)
{
// l2bias use to control position weight of l2char
// example (*=l2char) XX*X must come before X*XX
strcpy (p,p+1) ;
tstr[len-1] = l2bias + t_ctype0[1]- L2_GARAN +1 ;
p-- ;
continue ;
}
}
else
{
l2bias -= 8 ;
*p = to_lower_tis620[c];
}
/*
this routine skip non-printable char
but not necessary, leave it like raw ascii 8 bits
*/
/*
t_ctype0 = t_ctype[p[0]];
if ((t_ctype0[0]|t_ctype0[1]|t_ctype0[2])==IGNORE)
{
strcpy(p,p+1);
p-- ;
}
*/
}
}
/*
NOTE: isn't it faster to alloc buffer in calling function?
Convert thai string to "Standard C String Function" sortable string
Arg: const source string and length of converted string
Ret: Sortable string
*/
/*
Sathit's NOTE: we don't use this function anymore
static uchar* thai2sortable(const uchar * tstr,int len)
static void _thai2sortable(uchar *tstr)
{
*/
/* We use only 3 levels (neglect capitalization). */
/*
const uchar* p= tstr;
uchar *outBuf;
uchar *pRight1, *pRight2, *pRight3;
uchar *pLeft1, *pLeft2, *pLeft3;
uint bufSize;
uint RightSize;
len= (int) strnlen((char*) tstr,len);
bufSize= (uint) buffsize((char*) tstr);
RightSize= sizeof(uchar) * (len + 1);
if (!(outBuf= pLeft1= pRight1=
(uchar *)malloc(sizeof(uchar) * bufSize + RightSize*2)))
return (uchar*) tstr;
pLeft2= pRight2= pRight1 + sizeof(uchar) * bufSize;
pLeft3= pRight3= pRight2 + RightSize;
while (--len > 0)
uchar *p;
int len, tlen;
uchar l2bias;
tlen= len= strlen (tstr);
l2bias= 256 - 8;
for (p= tstr; tlen > 0; p++, tlen--)
{
int *t_ctype0= t_ctype[p[0]];
if (isldvowel(*p) && isconsnt(p[1]))
uchar c= *p;
if (isthai(c))
{
int *t_ctype1= t_ctype[p[1]];
*pRight1++= t_ctype1[0];
*pRight2++= t_ctype1[1];
*pRight3++= t_ctype1[2];
*pRight1++= t_ctype0[0];
*pRight2++= t_ctype0[1];
*pRight3++= t_ctype0[2];
p+= 2;
len--;
int *t_ctype0= t_ctype[c];
if (isconsnt(c))
l2bias -= 8;
if (isldvowel(c) && isconsnt(p[1]))
{
/* simply swap between leading-vowel and consonant */
*p= p[1];
p[1]= c;
tlen--;
p++;
continue;
}
/* if found level 2 char (L2_GARAN,L2_TONE*,L2_TYKHU) move to last */
if (t_ctype0[1] >= L2_GARAN)
{
/*
l2bias use to control position weight of l2char
example (*=l2char) XX*X must come before X*XX
*/
strmov(p,p+1);
tstr[len-1]= l2bias + t_ctype0[1]- L2_GARAN +1;
p--;
continue;
}
}
else
{
*pRight1= t_ctype0[0];
if(*pRight1 != IGNORE)
pRight1++;
*pRight2= t_ctype0[1];
if (*pRight2 != IGNORE)
pRight2++;
*pRight3= t_ctype0[2];
if(*pRight3 != IGNORE)
pRight3++;
p++;
l2bias-= 8;
*p= to_lower_tis620[c];
}
}
if (!len)
{
int *t_ctype0= t_ctype[p[0]];
*pRight1= t_ctype0[0];
if (*pRight1 != IGNORE)
pRight1++;
*pRight2= t_ctype0[1];
if (*pRight2 != IGNORE)
pRight2++;
*pRight3= t_ctype0[2];
if (*pRight3 != IGNORE)
pRight3++;
}
*pRight1++= L2_BLANK;
*pRight2++= L3_BLANK;
*pRight3++= '\0';
memcpy(pRight1, pLeft2, pRight2 - pLeft2);
pRight1+= pRight2 - pLeft2;
memcpy(pRight1, pLeft3, pRight3 - pLeft3);
return outBuf;
}
*/
/* strncoll() replacement, compare 2 string, both are conveted to sortable string
Arg: 2 Strings and it compare length
Ret: strcmp result
/*
strncoll() replacement, compare 2 string, both are converted to sortable
string
Arg: 2 Strings and it compare length
Ret: strcmp result
*/
int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2)
{
uchar buf[80] ;
uchar *tc1, *tc2;
int i;
len1= (int) strnlen((char*) s1,len1);
len2= (int) strnlen((char*) s2,len2);
if ((len1 + len2 +2) > (int) sizeof(buf))
tc1 = (uchar *)malloc(len1+len2) ;
else
tc1 = buf ;
tc2 = tc1 + len1+1 ;
strncpy((char *)tc1,(char *)s1,len1) ;
tc1[len1] = 0; // if s1's length > len1, need to put 'end of string'
strncpy((char *)tc2,(char *)s2,len2) ;
tc2[len2] = 0; // put end of string
_thai2sortable(tc1);
_thai2sortable(tc2);
i= strcmp((char*)tc1, (char*)tc2);
if (tc1 != buf )
free(tc1);
return i;
uchar buf[80] ;
uchar *tc1, *tc2;
int i;
len1= (int) strnlen((char*) s1,len1);
len2= (int) strnlen((char*) s2,len2);
tc1= buf;
if ((len1 + len2 +2) > (int) sizeof(buf))
tc1= (uchar*) malloc(len1+len2);
tc2= tc1 + len1+1;
memcpy((char*) tc1, (char*) s1, len1);
tc1[len1]= 0; /* if length(s1)> len1, need to put 'end of string' */
memcpy((char *)tc2, (char *)s2, len2);
tc2[len2]= 0; /* put end of string */
_thai2sortable(tc1);
_thai2sortable(tc2);
i= strcmp((char*)tc1, (char*)tc2);
if (tc1 != buf)
free(tc1);
return i;
}
/* strnxfrm replacment, convert Thai string to sortable string
Arg: Destination buffer, source string, dest length and source length
Ret: Conveted string size
/*
strnxfrm replacment, convert Thai string to sortable string
Arg: Destination buffer, source string, dest length and source length
Ret: Conveted string size
*/
int my_strnxfrm_tis620(uchar * dest, const uchar * src, int len, int srclen)
{
if (len > srclen)
len = srclen ;
strncpy (dest,src,len) ;
dest[len] = 0; // if src's length > len, need to put 'end of string'
_thai2sortable(dest);
return strlen(dest);
if (len > srclen)
len= srclen ;
strnmov(dest, src, len) ;
dest[len]= 0; /* if length(src) > len, need to put 'end of string' */
_thai2sortable(dest);
return strlen(dest);
}
/* strcoll replacment, compare 2 strings
Arg: 2 strings
Ret: strcmp result
/*
strcoll replacment, compare 2 strings
Arg: 2 strings
Ret: strcmp result
*/
int my_strcoll_tis620(const uchar * s1, const uchar * s2)
{
return my_strnncoll_tis620(s1, strlen((char *)s1),s2,strlen((char *)s2));
return my_strnncoll_tis620(s1, strlen((char *)s1),s2,strlen((char *)s2));
}
/* strxfrm replacment, convert Thai string to sortable string
Arg: Destination buffer, String and dest buffer size
Ret: Converting string size
/*
strxfrm replacment, convert Thai string to sortable string
Arg: Destination buffer, String and dest buffer size
Ret: Converting string size
*/
int my_strxfrm_tis620(uchar * dest, const uchar * src, int len)
{
return my_strnxfrm_tis620(dest,src,len,strlen((char *)src));
}
/* Convert SQL like string to C string
Arg: String, its length, escape character, resource length, minimal string and maximum string
Ret: Alway 0
/*
Convert SQL LIKE string to C string
Arg: String, its length, escape character, resource length,
minimal string and maximum string
Ret: Always 0
*/
/*
We just copy this function from opt_range.cc. No need to convert to
thai2sortable string. min_str and max_str will be use for comparison and
converted there.
*/
/* We just copy this function from opt_range.cc. No need to convert to
thai2sortable string. min_str and max_str will be use for comparison and
converted there. */
#define max_sort_chr ((char) 255)
#define wild_one '_'
#define wild_many '%'
my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape,
uint res_length, char *min_str, char *max_str,
uint *min_length, uint *max_length)
uint res_length, char *min_str, char *max_str,
uint *min_length, uint *max_length)
{
const char *end=ptr+ptr_length;
char *min_org=min_str;
......@@ -692,7 +627,7 @@ my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape,
*min_length= (uint) (min_str - min_org);
*max_length=res_length;
do {
*min_str++ = ' '; /* Because if key compression */
*min_str++ = ' '; /* Because of key compression */
*max_str++ = max_sort_chr;
} while (min_str != min_end);
return 0;
......@@ -702,18 +637,21 @@ my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape,
*min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end)
*min_str++ = *max_str++ = ' '; /* Because if key compression */
*min_str++= *max_str++ = ' '; /* Because of key compression */
return 0;
}
/* Thai normalization for input sub system
Arg: Buffer, 's length, String, 'length
Ret: Void
/*
Thai normalization for input sub system
Arg: Buffer, 's length, String, 'length
*/
void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length)
{
const uchar* fr= from;
uchar* p= ptr;
const uchar *fr= from;
uchar *p= ptr;
uint i;
if (length > field_length)
......@@ -721,24 +659,21 @@ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length)
for (i=0;i<length;i++,p++,fr++)
{
*p = *fr ;
*p= *fr ;
/* Sathit's NOTE: it's better idea not to do any normalize
*/
if (istone(*fr) || isdiacrt1(*fr))
{
if (i > 0 && (islwrvowel(fr[-1]) || isuprvowel(fr[-1])))
continue ;
if(islwrvowel(fr[1]) || isuprvowel(fr[1]))
{
*p= fr[1];
p[1]= *fr;
fr++;
p++;
i++ ;
}
/* Sathit's NOTE: it's better idea not to do any normalize */
if (istone(*fr) || isdiacrt1(*fr))
{
if (i > 0 && (islwrvowel(fr[-1]) || isuprvowel(fr[-1])))
continue;
if(islwrvowel(fr[1]) || isuprvowel(fr[1]))
{
*p= fr[1];
p[1]= *fr;
fr++;
p++;
i++;
}
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment