Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
7a84e124
Commit
7a84e124
authored
Sep 28, 2006
by
gkodinov@dl145s.mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal:/home/bk/mysql-5.1-opt
into dl145s.mysql.com:/data/bk/team_tree_merge/MERGE/mysql-5.1-opt
parents
3abb6043
16f59a5e
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
402 additions
and
167 deletions
+402
-167
mysql-test/r/func_in.result
mysql-test/r/func_in.result
+68
-0
mysql-test/t/func_in.test
mysql-test/t/func_in.test
+24
-0
mysql-test/t/view.test
mysql-test/t/view.test
+1
-1
sql/item.cc
sql/item.cc
+0
-5
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+184
-112
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+116
-48
sql/opt_range.cc
sql/opt_range.cc
+9
-1
No files found.
mysql-test/r/func_in.result
View file @
7a84e124
...
@@ -343,3 +343,71 @@ some_id
...
@@ -343,3 +343,71 @@ some_id
1
1
2
2
drop table t1;
drop table t1;
create table t1(f1 char(1));
insert into t1 values ('a'),('b'),('1');
select f1 from t1 where f1 in ('a',1);
f1
a
1
select f1, case f1 when 'a' then '+' when 1 then '-' end from t1;
f1 case f1 when 'a' then '+' when 1 then '-' end
a +
b NULL
1 -
create index t1f1_idx on t1(f1);
select f1 from t1 where f1 in ('a',1);
f1
1
a
explain select f1 from t1 where f1 in ('a',1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL t1f1_idx 2 NULL 3 Using where; Using index
select f1 from t1 where f1 in ('a','b');
f1
a
b
explain select f1 from t1 where f1 in ('a','b');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index t1f1_idx t1f1_idx 2 NULL 3 Using where; Using index
select f1 from t1 where f1 in (2,1);
f1
1
explain select f1 from t1 where f1 in (2,1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index t1f1_idx t1f1_idx 2 NULL 3 Using where; Using index
create table t2(f2 int, index t2f2(f2));
insert into t2 values(0),(1),(2);
select f2 from t2 where f2 in ('a',2);
f2
0
2
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'a'
explain select f2 from t2 where f2 in ('a',2);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL t2f2 5 NULL 3 Using where; Using index
select f2 from t2 where f2 in ('a','b');
f2
0
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'b'
explain select f2 from t2 where f2 in ('a','b');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index t2f2 t2f2 5 NULL 3 Using where; Using index
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
Warning 1292 Truncated incorrect DOUBLE value: 'b'
select f2 from t2 where f2 in (1,'b');
f2
0
1
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'b'
Warning 1292 Truncated incorrect DOUBLE value: 'b'
explain select f2 from t2 where f2 in (1,'b');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index NULL t2f2 5 NULL 3 Using where; Using index
drop table t1, t2;
mysql-test/t/func_in.test
View file @
7a84e124
...
@@ -232,3 +232,27 @@ select some_id from t1 where some_id not in(2,-1);
...
@@ -232,3 +232,27 @@ select some_id from t1 where some_id not in(2,-1);
select
some_id
from
t1
where
some_id
not
in
(
-
4
,
-
1
,
-
4
);
select
some_id
from
t1
where
some_id
not
in
(
-
4
,
-
1
,
-
4
);
select
some_id
from
t1
where
some_id
not
in
(
-
4
,
-
1
,
3423534
,
2342342
);
select
some_id
from
t1
where
some_id
not
in
(
-
4
,
-
1
,
3423534
,
2342342
);
drop
table
t1
;
drop
table
t1
;
#
# Bug#18360: Type aggregation for IN and CASE may lead to a wrong result
#
create
table
t1
(
f1
char
(
1
));
insert
into
t1
values
(
'a'
),(
'b'
),(
'1'
);
select
f1
from
t1
where
f1
in
(
'a'
,
1
);
select
f1
,
case
f1
when
'a'
then
'+'
when
1
then
'-'
end
from
t1
;
create
index
t1f1_idx
on
t1
(
f1
);
select
f1
from
t1
where
f1
in
(
'a'
,
1
);
explain
select
f1
from
t1
where
f1
in
(
'a'
,
1
);
select
f1
from
t1
where
f1
in
(
'a'
,
'b'
);
explain
select
f1
from
t1
where
f1
in
(
'a'
,
'b'
);
select
f1
from
t1
where
f1
in
(
2
,
1
);
explain
select
f1
from
t1
where
f1
in
(
2
,
1
);
create
table
t2
(
f2
int
,
index
t2f2
(
f2
));
insert
into
t2
values
(
0
),(
1
),(
2
);
select
f2
from
t2
where
f2
in
(
'a'
,
2
);
explain
select
f2
from
t2
where
f2
in
(
'a'
,
2
);
select
f2
from
t2
where
f2
in
(
'a'
,
'b'
);
explain
select
f2
from
t2
where
f2
in
(
'a'
,
'b'
);
select
f2
from
t2
where
f2
in
(
1
,
'b'
);
explain
select
f2
from
t2
where
f2
in
(
1
,
'b'
);
drop
table
t1
,
t2
;
mysql-test/t/view.test
View file @
7a84e124
...
@@ -2443,7 +2443,7 @@ DROP TABLE t1, t2;
...
@@ -2443,7 +2443,7 @@ DROP TABLE t1, t2;
#
#
# Bug #16069: VIEW does return the same results as underlying SELECT
# Bug #16069: VIEW does return the same results as underlying SELECT
# with WHERE condition containing BETWEEN over dates
# with WHERE condition containing BETWEEN over dates
# Dates as strings should be casted to date type
CREATE
TABLE
t1
(
id
int
NOT
NULL
PRIMARY
KEY
,
CREATE
TABLE
t1
(
id
int
NOT
NULL
PRIMARY
KEY
,
td
date
DEFAULT
NULL
,
KEY
idx
(
td
));
td
date
DEFAULT
NULL
,
KEY
idx
(
td
));
...
...
sql/item.cc
View file @
7a84e124
...
@@ -5711,11 +5711,6 @@ void Item_trigger_field::cleanup()
...
@@ -5711,11 +5711,6 @@ void Item_trigger_field::cleanup()
}
}
/*
If item is a const function, calculate it and return a const item
The original item is freed if not returned
*/
Item_result
item_cmp_type
(
Item_result
a
,
Item_result
b
)
Item_result
item_cmp_type
(
Item_result
a
,
Item_result
b
)
{
{
if
(
a
==
STRING_RESULT
&&
b
==
STRING_RESULT
)
if
(
a
==
STRING_RESULT
&&
b
==
STRING_RESULT
)
...
...
sql/item_cmpfunc.cc
View file @
7a84e124
...
@@ -66,12 +66,10 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
...
@@ -66,12 +66,10 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
/*
/*
Aggregates result types from the array of items.
Aggregates result types from the array of items.
SYNOPSIS
:
SYNOPSIS
agg_cmp_type()
agg_cmp_type()
thd thread handle
items array of items to aggregate the type from
type [out] the aggregated type
nitems number of items in the array
items array of items to aggregate the type from
nitems number of items in the array
DESCRIPTION
DESCRIPTION
This function aggregates result types from the array of items. Found type
This function aggregates result types from the array of items. Found type
...
@@ -79,12 +77,43 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
...
@@ -79,12 +77,43 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
Aggregation itself is performed by the item_cmp_type() function.
Aggregation itself is performed by the item_cmp_type() function.
*/
*/
static
void
agg_cmp_type
(
THD
*
thd
,
Item_result
*
type
,
Item
**
items
,
uint
nitems
)
static
Item_result
agg_cmp_type
(
Item
**
items
,
uint
nitems
)
{
{
uint
i
;
uint
i
;
type
[
0
]
=
items
[
0
]
->
result_type
();
Item_result
type
=
items
[
0
]
->
result_type
();
for
(
i
=
1
;
i
<
nitems
;
i
++
)
for
(
i
=
1
;
i
<
nitems
;
i
++
)
type
[
0
]
=
item_cmp_type
(
type
[
0
],
items
[
i
]
->
result_type
());
type
=
item_cmp_type
(
type
,
items
[
i
]
->
result_type
());
return
type
;
}
/*
Collects different types for comparison of first item with each other items
SYNOPSIS
collect_cmp_types()
items Array of items to collect types from
nitems Number of items in the array
DESCRIPTION
This function collects different result types for comparison of the first
item in the list with each of the remaining items in the 'items' array.
RETURN
Bitmap of collected types
*/
static
uint
collect_cmp_types
(
Item
**
items
,
uint
nitems
)
{
uint
i
;
uint
found_types
;
Item_result
left_result
=
items
[
0
]
->
result_type
();
DBUG_ASSERT
(
nitems
>
1
);
found_types
=
0
;
for
(
i
=
1
;
i
<
nitems
;
i
++
)
found_types
|=
1
<<
(
uint
)
item_cmp_type
(
left_result
,
items
[
i
]
->
result_type
());
return
found_types
;
}
}
...
@@ -1117,7 +1146,7 @@ void Item_func_between::fix_length_and_dec()
...
@@ -1117,7 +1146,7 @@ void Item_func_between::fix_length_and_dec()
*/
*/
if
(
!
args
[
0
]
||
!
args
[
1
]
||
!
args
[
2
])
if
(
!
args
[
0
]
||
!
args
[
1
]
||
!
args
[
2
])
return
;
return
;
agg_cmp_type
(
thd
,
&
cmp_type
,
args
,
3
);
cmp_type
=
agg_cmp_type
(
args
,
3
);
if
(
cmp_type
==
STRING_RESULT
&&
if
(
cmp_type
==
STRING_RESULT
&&
agg_arg_charsets
(
cmp_collation
,
args
,
3
,
MY_COLL_CMP_CONV
,
1
))
agg_arg_charsets
(
cmp_collation
,
args
,
3
,
MY_COLL_CMP_CONV
,
1
))
return
;
return
;
...
@@ -1597,94 +1626,65 @@ Item_func_nullif::is_null()
...
@@ -1597,94 +1626,65 @@ Item_func_nullif::is_null()
return
(
null_value
=
(
!
cmp
.
compare
()
?
1
:
args
[
0
]
->
null_value
));
return
(
null_value
=
(
!
cmp
.
compare
()
?
1
:
args
[
0
]
->
null_value
));
}
}
/*
/*
CASE expression
Return the matching ITEM or NULL if all compares (including else) failed
Return the matching ITEM or NULL if all compares (including else) failed
SYNOPSIS
find_item()
str Buffer string
DESCRIPTION
Find and return matching items for CASE or ELSE item if all compares
are failed or NULL if ELSE item isn't defined.
IMPLEMENTATION
In order to do correct comparisons of the CASE expression (the expression
between CASE and the first WHEN) with each WHEN expression several
comparators are used. One for each result type. CASE expression can be
evaluated up to # of different result types are used. To check whether
the CASE expression already was evaluated for a particular result type
a bit mapped variable value_added_map is used. Result types are mapped
to it according to their int values i.e. STRING_RESULT is mapped to bit
0, REAL_RESULT to bit 1, so on.
RETURN
NULL - Nothing found and there is no ELSE expression defined
item - Found item or ELSE item if defined and all comparisons are
failed
*/
*/
Item
*
Item_func_case
::
find_item
(
String
*
str
)
Item
*
Item_func_case
::
find_item
(
String
*
str
)
{
{
String
*
first_expr_str
,
*
tmp
;
uint
value_added_map
=
0
;
my_decimal
*
first_expr_dec
,
first_expr_dec_val
;
longlong
first_expr_int
;
double
first_expr_real
;
char
buff
[
MAX_FIELD_WIDTH
];
String
buff_str
(
buff
,
sizeof
(
buff
),
default_charset
());
/* These will be initialized later */
LINT_INIT
(
first_expr_str
);
LINT_INIT
(
first_expr_int
);
LINT_INIT
(
first_expr_real
);
LINT_INIT
(
first_expr_dec
);
if
(
first_expr_num
!=
-
1
)
{
switch
(
cmp_type
)
{
case
STRING_RESULT
:
// We can't use 'str' here as this may be overwritten
if
(
!
(
first_expr_str
=
args
[
first_expr_num
]
->
val_str
(
&
buff_str
)))
return
else_expr_num
!=
-
1
?
args
[
else_expr_num
]
:
0
;
// Impossible
break
;
case
INT_RESULT
:
first_expr_int
=
args
[
first_expr_num
]
->
val_int
();
if
(
args
[
first_expr_num
]
->
null_value
)
return
else_expr_num
!=
-
1
?
args
[
else_expr_num
]
:
0
;
break
;
case
REAL_RESULT
:
first_expr_real
=
args
[
first_expr_num
]
->
val_real
();
if
(
args
[
first_expr_num
]
->
null_value
)
return
else_expr_num
!=
-
1
?
args
[
else_expr_num
]
:
0
;
break
;
case
DECIMAL_RESULT
:
first_expr_dec
=
args
[
first_expr_num
]
->
val_decimal
(
&
first_expr_dec_val
);
if
(
args
[
first_expr_num
]
->
null_value
)
return
else_expr_num
!=
-
1
?
args
[
else_expr_num
]
:
0
;
break
;
case
ROW_RESULT
:
default:
// This case should never be chosen
DBUG_ASSERT
(
0
);
break
;
}
}
// Compare every WHEN argument with it and return the first match
if
(
first_expr_num
==
-
1
)
for
(
uint
i
=
0
;
i
<
ncases
;
i
+=
2
)
{
{
if
(
first_expr_num
==
-
1
)
for
(
uint
i
=
0
;
i
<
ncases
;
i
+=
2
)
{
{
// No expression between CASE and the first WHEN
// No expression between CASE and the first WHEN
if
(
args
[
i
]
->
val_bool
())
if
(
args
[
i
]
->
val_bool
())
return
args
[
i
+
1
];
return
args
[
i
+
1
];
continue
;
continue
;
}
}
switch
(
cmp_type
)
{
}
case
STRING_RESULT
:
else
if
((
tmp
=
args
[
i
]
->
val_str
(
str
)))
// If not null
{
if
(
sortcmp
(
tmp
,
first_expr_str
,
cmp_collation
.
collation
)
==
0
)
/* Compare every WHEN argument with it and return the first match */
return
args
[
i
+
1
];
for
(
uint
i
=
0
;
i
<
ncases
;
i
+=
2
)
break
;
case
INT_RESULT
:
if
(
args
[
i
]
->
val_int
()
==
first_expr_int
&&
!
args
[
i
]
->
null_value
)
return
args
[
i
+
1
];
break
;
case
REAL_RESULT
:
if
(
args
[
i
]
->
val_real
()
==
first_expr_real
&&
!
args
[
i
]
->
null_value
)
return
args
[
i
+
1
];
break
;
case
DECIMAL_RESULT
:
{
{
my_decimal
value
;
cmp_type
=
item_cmp_type
(
left_result_type
,
args
[
i
]
->
result_type
());
if
(
my_decimal_cmp
(
args
[
i
]
->
val_decimal
(
&
value
),
first_expr_dec
)
==
0
)
DBUG_ASSERT
(
cmp_type
!=
ROW_RESULT
);
return
args
[
i
+
1
];
DBUG_ASSERT
(
cmp_items
[(
uint
)
cmp_type
]);
break
;
if
(
!
(
value_added_map
&
(
1
<<
(
uint
)
cmp_type
)))
}
{
case
ROW_RESULT
:
cmp_items
[(
uint
)
cmp_type
]
->
store_value
(
args
[
first_expr_num
]);
default:
if
((
null_value
=
args
[
first_expr_num
]
->
null_value
))
// This case should never be chosen
return
else_expr_num
!=
-
1
?
args
[
else_expr_num
]
:
0
;
DBUG_ASSERT
(
0
);
value_added_map
|=
1
<<
(
uint
)
cmp_type
;
break
;
}
if
(
!
cmp_items
[(
uint
)
cmp_type
]
->
cmp
(
args
[
i
])
&&
!
args
[
i
]
->
null_value
)
return
args
[
i
+
1
];
}
}
}
}
// No, WHEN clauses all missed, return ELSE expression
// No, WHEN clauses all missed, return ELSE expression
...
@@ -1791,7 +1791,7 @@ void Item_func_case::fix_length_and_dec()
...
@@ -1791,7 +1791,7 @@ void Item_func_case::fix_length_and_dec()
Item
**
agg
;
Item
**
agg
;
uint
nagg
;
uint
nagg
;
THD
*
thd
=
current_thd
;
THD
*
thd
=
current_thd
;
uint
found_types
=
0
;
if
(
!
(
agg
=
(
Item
**
)
sql_alloc
(
sizeof
(
Item
*
)
*
(
ncases
+
1
))))
if
(
!
(
agg
=
(
Item
**
)
sql_alloc
(
sizeof
(
Item
*
)
*
(
ncases
+
1
))))
return
;
return
;
...
@@ -1818,16 +1818,31 @@ void Item_func_case::fix_length_and_dec()
...
@@ -1818,16 +1818,31 @@ void Item_func_case::fix_length_and_dec()
*/
*/
if
(
first_expr_num
!=
-
1
)
if
(
first_expr_num
!=
-
1
)
{
{
uint
i
;
agg
[
0
]
=
args
[
first_expr_num
];
agg
[
0
]
=
args
[
first_expr_num
];
left_result_type
=
agg
[
0
]
->
result_type
();
for
(
nagg
=
0
;
nagg
<
ncases
/
2
;
nagg
++
)
for
(
nagg
=
0
;
nagg
<
ncases
/
2
;
nagg
++
)
agg
[
nagg
+
1
]
=
args
[
nagg
*
2
];
agg
[
nagg
+
1
]
=
args
[
nagg
*
2
];
nagg
++
;
nagg
++
;
agg_cmp_type
(
thd
,
&
cmp_type
,
agg
,
nagg
);
found_types
=
collect_cmp_types
(
agg
,
nagg
);
if
((
cmp_type
==
STRING_RESULT
)
&&
agg_arg_charsets
(
cmp_collation
,
agg
,
nagg
,
MY_COLL_CMP_CONV
,
1
))
for
(
i
=
0
;
i
<=
(
uint
)
DECIMAL_RESULT
;
i
++
)
return
;
{
if
(
found_types
&
(
1
<<
i
)
&&
!
cmp_items
[
i
])
{
DBUG_ASSERT
((
Item_result
)
i
!=
ROW_RESULT
);
if
((
Item_result
)
i
==
STRING_RESULT
&&
agg_arg_charsets
(
cmp_collation
,
agg
,
nagg
,
MY_COLL_CMP_CONV
,
1
))
return
;
if
(
!
(
cmp_items
[
i
]
=
cmp_item
::
get_comparator
((
Item_result
)
i
,
cmp_collation
.
collation
)))
return
;
}
}
}
}
if
(
else_expr_num
==
-
1
||
args
[
else_expr_num
]
->
maybe_null
)
if
(
else_expr_num
==
-
1
||
args
[
else_expr_num
]
->
maybe_null
)
maybe_null
=
1
;
maybe_null
=
1
;
...
@@ -2412,16 +2427,14 @@ static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
...
@@ -2412,16 +2427,14 @@ static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
void
Item_func_in
::
fix_length_and_dec
()
void
Item_func_in
::
fix_length_and_dec
()
{
{
Item
**
arg
,
**
arg_end
;
Item
**
arg
,
**
arg_end
;
uint
const_itm
=
1
;
bool
const_itm
=
1
;
THD
*
thd
=
current_thd
;
THD
*
thd
=
current_thd
;
uint
found_types
=
0
;
uint
type_cnt
=
0
,
i
;
left_result_type
=
args
[
0
]
->
result_type
();
found_types
=
collect_cmp_types
(
args
,
arg_count
);
agg_cmp_type
(
thd
,
&
cmp_type
,
args
,
arg_count
);
for
(
arg
=
args
+
1
,
arg_end
=
args
+
arg_count
;
arg
!=
arg_end
;
arg
++
)
if
(
cmp_type
==
STRING_RESULT
&&
agg_arg_charsets
(
cmp_collation
,
args
,
arg_count
,
MY_COLL_CMP_CONV
,
1
))
return
;
for
(
arg
=
args
+
1
,
arg_end
=
args
+
arg_count
;
arg
!=
arg_end
;
arg
++
)
{
{
if
(
!
arg
[
0
]
->
const_item
())
if
(
!
arg
[
0
]
->
const_item
())
{
{
...
@@ -2429,26 +2442,39 @@ void Item_func_in::fix_length_and_dec()
...
@@ -2429,26 +2442,39 @@ void Item_func_in::fix_length_and_dec()
break
;
break
;
}
}
}
}
for
(
i
=
0
;
i
<=
(
uint
)
DECIMAL_RESULT
;
i
++
)
{
if
(
found_types
&
1
<<
i
)
(
type_cnt
)
++
;
}
/*
/*
Row item with NULLs inside can return NULL or FALSE =>
Row item with NULLs inside can return NULL or FALSE =>
they can't be processed as static
they can't be processed as static
*/
*/
if
(
const_itm
&&
!
nulls_in_row
())
if
(
type_cnt
==
1
&&
const_itm
&&
!
nulls_in_row
())
{
{
uint
tmp_type
;
Item_result
cmp_type
;
/* Only one cmp type was found. Extract it here */
for
(
tmp_type
=
0
;
found_types
-
1
;
found_types
>>=
1
)
tmp_type
++
;
cmp_type
=
(
Item_result
)
tmp_type
;
switch
(
cmp_type
)
{
switch
(
cmp_type
)
{
case
STRING_RESULT
:
case
STRING_RESULT
:
array
=
new
in_string
(
arg_count
-
1
,(
qsort2_cmp
)
srtcmp_in
,
if
(
agg_arg_charsets
(
cmp_collation
,
args
,
arg_count
,
MY_COLL_CMP_CONV
,
1
))
return
;
array
=
new
in_string
(
arg_count
-
1
,(
qsort2_cmp
)
srtcmp_in
,
cmp_collation
.
collation
);
cmp_collation
.
collation
);
break
;
break
;
case
INT_RESULT
:
case
INT_RESULT
:
array
=
new
in_longlong
(
arg_count
-
1
);
array
=
new
in_longlong
(
arg_count
-
1
);
break
;
break
;
case
REAL_RESULT
:
case
REAL_RESULT
:
array
=
new
in_double
(
arg_count
-
1
);
array
=
new
in_double
(
arg_count
-
1
);
break
;
break
;
case
ROW_RESULT
:
case
ROW_RESULT
:
array
=
new
in_row
(
arg_count
-
1
,
args
[
0
]);
array
=
new
in_row
(
arg_count
-
1
,
args
[
0
]);
break
;
break
;
case
DECIMAL_RESULT
:
case
DECIMAL_RESULT
:
array
=
new
in_decimal
(
arg_count
-
1
);
array
=
new
in_decimal
(
arg_count
-
1
);
...
@@ -2468,15 +2494,25 @@ void Item_func_in::fix_length_and_dec()
...
@@ -2468,15 +2494,25 @@ void Item_func_in::fix_length_and_dec()
else
else
have_null
=
1
;
have_null
=
1
;
}
}
if
((
array
->
used_count
=
j
))
if
((
array
->
used_count
=
j
))
array
->
sort
();
array
->
sort
();
}
}
}
}
else
else
{
{
in_item
=
cmp_item
::
get_comparator
(
cmp_type
,
cmp_collation
.
collation
);
for
(
i
=
0
;
i
<=
(
uint
)
DECIMAL_RESULT
;
i
++
)
if
(
cmp_type
==
STRING_RESULT
)
{
in_item
->
cmp_charset
=
cmp_collation
.
collation
;
if
(
found_types
&
(
1
<<
i
)
&&
!
cmp_items
[
i
])
{
if
((
Item_result
)
i
==
STRING_RESULT
&&
agg_arg_charsets
(
cmp_collation
,
args
,
arg_count
,
MY_COLL_CMP_CONV
,
1
))
return
;
if
(
!
(
cmp_items
[
i
]
=
cmp_item
::
get_comparator
((
Item_result
)
i
,
cmp_collation
.
collation
)))
return
;
}
}
}
}
maybe_null
=
args
[
0
]
->
maybe_null
;
maybe_null
=
args
[
0
]
->
maybe_null
;
max_length
=
1
;
max_length
=
1
;
...
@@ -2495,25 +2531,61 @@ void Item_func_in::print(String *str)
...
@@ -2495,25 +2531,61 @@ void Item_func_in::print(String *str)
}
}
/*
Evaluate the function and return its value.
SYNOPSIS
val_int()
DESCRIPTION
Evaluate the function and return its value.
IMPLEMENTATION
If the array object is defined then the value of the function is
calculated by means of this array.
Otherwise several cmp_item objects are used in order to do correct
comparison of left expression and an expression from the values list.
One cmp_item object correspond to one used comparison type. Left
expression can be evaluated up to number of different used comparison
types. A bit mapped variable value_added_map is used to check whether
the left expression already was evaluated for a particular result type.
Result types are mapped to it according to their integer values i.e.
STRING_RESULT is mapped to bit 0, REAL_RESULT to bit 1, so on.
RETURN
Value of the function
*/
longlong
Item_func_in
::
val_int
()
longlong
Item_func_in
::
val_int
()
{
{
cmp_item
*
in_item
;
DBUG_ASSERT
(
fixed
==
1
);
DBUG_ASSERT
(
fixed
==
1
);
uint
value_added_map
=
0
;
if
(
array
)
if
(
array
)
{
{
int
tmp
=
array
->
find
(
args
[
0
]);
int
tmp
=
array
->
find
(
args
[
0
]);
null_value
=
args
[
0
]
->
null_value
||
(
!
tmp
&&
have_null
);
null_value
=
args
[
0
]
->
null_value
||
(
!
tmp
&&
have_null
);
return
(
longlong
)
(
!
null_value
&&
tmp
!=
negated
);
return
(
longlong
)
(
!
null_value
&&
tmp
!=
negated
);
}
}
in_item
->
store_value
(
args
[
0
]);
if
((
null_value
=
args
[
0
]
->
null_value
))
for
(
uint
i
=
1
;
i
<
arg_count
;
i
++
)
return
0
;
have_null
=
0
;
for
(
uint
i
=
1
;
i
<
arg_count
;
i
++
)
{
{
Item_result
cmp_type
=
item_cmp_type
(
left_result_type
,
args
[
i
]
->
result_type
());
in_item
=
cmp_items
[(
uint
)
cmp_type
];
DBUG_ASSERT
(
in_item
);
if
(
!
(
value_added_map
&
(
1
<<
(
uint
)
cmp_type
)))
{
in_item
->
store_value
(
args
[
0
]);
if
((
null_value
=
args
[
0
]
->
null_value
))
return
0
;
have_null
=
0
;
value_added_map
|=
1
<<
(
uint
)
cmp_type
;
}
if
(
!
in_item
->
cmp
(
args
[
i
])
&&
!
args
[
i
]
->
null_value
)
if
(
!
in_item
->
cmp
(
args
[
i
])
&&
!
args
[
i
]
->
null_value
)
return
(
longlong
)
(
!
negated
);
return
(
longlong
)
(
!
negated
);
have_null
|=
args
[
i
]
->
null_value
;
have_null
|=
args
[
i
]
->
null_value
;
}
}
null_value
=
have_null
;
null_value
=
have_null
;
return
(
longlong
)
(
!
null_value
&&
negated
);
return
(
longlong
)
(
!
null_value
&&
negated
);
}
}
...
...
sql/item_cmpfunc.h
View file @
7a84e124
...
@@ -589,49 +589,6 @@ class Item_func_nullif :public Item_bool_func2
...
@@ -589,49 +589,6 @@ class Item_func_nullif :public Item_bool_func2
};
};
class
Item_func_case
:
public
Item_func
{
int
first_expr_num
,
else_expr_num
;
enum
Item_result
cached_result_type
;
String
tmp_value
;
uint
ncases
;
Item_result
cmp_type
;
DTCollation
cmp_collation
;
public:
Item_func_case
(
List
<
Item
>
&
list
,
Item
*
first_expr_arg
,
Item
*
else_expr_arg
)
:
Item_func
(),
first_expr_num
(
-
1
),
else_expr_num
(
-
1
),
cached_result_type
(
INT_RESULT
)
{
ncases
=
list
.
elements
;
if
(
first_expr_arg
)
{
first_expr_num
=
list
.
elements
;
list
.
push_back
(
first_expr_arg
);
}
if
(
else_expr_arg
)
{
else_expr_num
=
list
.
elements
;
list
.
push_back
(
else_expr_arg
);
}
set_arguments
(
list
);
}
double
val_real
();
longlong
val_int
();
String
*
val_str
(
String
*
);
my_decimal
*
val_decimal
(
my_decimal
*
);
bool
fix_fields
(
THD
*
thd
,
Item
**
ref
);
void
fix_length_and_dec
();
uint
decimal_precision
()
const
;
table_map
not_null_tables
()
const
{
return
0
;
}
enum
Item_result
result_type
()
const
{
return
cached_result_type
;
}
const
char
*
func_name
()
const
{
return
"case"
;
}
void
print
(
String
*
str
);
Item
*
find_item
(
String
*
str
);
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
bool
check_partition_func_processor
(
byte
*
bool_arg
)
{
return
0
;}
};
/* Functions to handle the optimized IN */
/* Functions to handle the optimized IN */
...
@@ -686,6 +643,7 @@ class in_vector :public Sql_alloc
...
@@ -686,6 +643,7 @@ class in_vector :public Sql_alloc
{
{
return
test
(
compare
(
collation
,
base
+
pos1
*
size
,
base
+
pos2
*
size
));
return
test
(
compare
(
collation
,
base
+
pos1
*
size
,
base
+
pos2
*
size
));
}
}
virtual
Item_result
result_type
()
=
0
;
};
};
class
in_string
:
public
in_vector
class
in_string
:
public
in_vector
...
@@ -707,6 +665,7 @@ class in_string :public in_vector
...
@@ -707,6 +665,7 @@ class in_string :public in_vector
Item_string
*
to
=
(
Item_string
*
)
item
;
Item_string
*
to
=
(
Item_string
*
)
item
;
to
->
str_value
=
*
str
;
to
->
str_value
=
*
str
;
}
}
Item_result
result_type
()
{
return
STRING_RESULT
;
}
};
};
class
in_longlong
:
public
in_vector
class
in_longlong
:
public
in_vector
...
@@ -729,6 +688,7 @@ class in_longlong :public in_vector
...
@@ -729,6 +688,7 @@ class in_longlong :public in_vector
{
{
((
Item_int
*
)
item
)
->
value
=
((
longlong
*
)
base
)[
pos
];
((
Item_int
*
)
item
)
->
value
=
((
longlong
*
)
base
)[
pos
];
}
}
Item_result
result_type
()
{
return
INT_RESULT
;
}
};
};
class
in_double
:
public
in_vector
class
in_double
:
public
in_vector
...
@@ -746,6 +706,7 @@ class in_double :public in_vector
...
@@ -746,6 +706,7 @@ class in_double :public in_vector
{
{
((
Item_float
*
)
item
)
->
value
=
((
double
*
)
base
)[
pos
];
((
Item_float
*
)
item
)
->
value
=
((
double
*
)
base
)[
pos
];
}
}
Item_result
result_type
()
{
return
REAL_RESULT
;
}
};
};
...
@@ -766,6 +727,8 @@ class in_decimal :public in_vector
...
@@ -766,6 +727,8 @@ class in_decimal :public in_vector
Item_decimal
*
item_dec
=
(
Item_decimal
*
)
item
;
Item_decimal
*
item_dec
=
(
Item_decimal
*
)
item
;
item_dec
->
set_decimal_value
(
dec
);
item_dec
->
set_decimal_value
(
dec
);
}
}
Item_result
result_type
()
{
return
DECIMAL_RESULT
;
}
};
};
...
@@ -796,7 +759,9 @@ class cmp_item_string :public cmp_item
...
@@ -796,7 +759,9 @@ class cmp_item_string :public cmp_item
protected:
protected:
String
*
value_res
;
String
*
value_res
;
public:
public:
cmp_item_string
()
{}
cmp_item_string
(
CHARSET_INFO
*
cs
)
{
cmp_charset
=
cs
;
}
cmp_item_string
(
CHARSET_INFO
*
cs
)
{
cmp_charset
=
cs
;
}
void
set_charset
(
CHARSET_INFO
*
cs
)
{
cmp_charset
=
cs
;
}
friend
class
cmp_item_sort_string
;
friend
class
cmp_item_sort_string
;
friend
class
cmp_item_sort_string_in_static
;
friend
class
cmp_item_sort_string_in_static
;
};
};
...
@@ -807,6 +772,8 @@ class cmp_item_sort_string :public cmp_item_string
...
@@ -807,6 +772,8 @@ class cmp_item_sort_string :public cmp_item_string
char
value_buff
[
STRING_BUFFER_USUAL_SIZE
];
char
value_buff
[
STRING_BUFFER_USUAL_SIZE
];
String
value
;
String
value
;
public:
public:
cmp_item_sort_string
()
:
cmp_item_string
()
{}
cmp_item_sort_string
(
CHARSET_INFO
*
cs
)
:
cmp_item_sort_string
(
CHARSET_INFO
*
cs
)
:
cmp_item_string
(
cs
),
cmp_item_string
(
cs
),
value
(
value_buff
,
sizeof
(
value_buff
),
cs
)
{}
value
(
value_buff
,
sizeof
(
value_buff
),
cs
)
{}
...
@@ -828,6 +795,11 @@ class cmp_item_sort_string :public cmp_item_string
...
@@ -828,6 +795,11 @@ class cmp_item_sort_string :public cmp_item_string
return
sortcmp
(
value_res
,
cmp
->
value_res
,
cmp_charset
);
return
sortcmp
(
value_res
,
cmp
->
value_res
,
cmp_charset
);
}
}
cmp_item
*
make_same
();
cmp_item
*
make_same
();
void
set_charset
(
CHARSET_INFO
*
cs
)
{
cmp_charset
=
cs
;
value
.
set_quick
(
value_buff
,
sizeof
(
value_buff
),
cs
);
}
};
};
class
cmp_item_int
:
public
cmp_item
class
cmp_item_int
:
public
cmp_item
...
@@ -908,6 +880,7 @@ class in_row :public in_vector
...
@@ -908,6 +880,7 @@ class in_row :public in_vector
~
in_row
();
~
in_row
();
void
set
(
uint
pos
,
Item
*
item
);
void
set
(
uint
pos
,
Item
*
item
);
byte
*
get_value
(
Item
*
item
);
byte
*
get_value
(
Item
*
item
);
Item_result
result_type
()
{
return
ROW_RESULT
;
}
};
};
/*
/*
...
@@ -943,18 +916,109 @@ class cmp_item_sort_string_in_static :public cmp_item_string
...
@@ -943,18 +916,109 @@ class cmp_item_sort_string_in_static :public cmp_item_string
}
}
};
};
/*
The class Item_func_case is the CASE ... WHEN ... THEN ... END function
implementation.
When there is no expression between CASE and the first WHEN
(the CASE expression) then this function simple checks all WHEN expressions
one after another. When some WHEN expression evaluated to TRUE then the
value of the corresponding THEN expression is returned.
When the CASE expression is specified then it is compared to each WHEN
expression individually. When an equal WHEN expression is found
corresponding THEN expression is returned.
In order to do correct comparisons several comparators are used. One for
each result type. Different result types that are used in particular
CASE ... END expression are collected in the fix_length_and_dec() member
function and only comparators for there result types are used.
*/
class
Item_func_case
:
public
Item_func
{
int
first_expr_num
,
else_expr_num
;
enum
Item_result
cached_result_type
,
left_result_type
;
String
tmp_value
;
uint
ncases
;
Item_result
cmp_type
;
DTCollation
cmp_collation
;
cmp_item
*
cmp_items
[
5
];
/* For all result types */
cmp_item
*
case_item
;
public:
Item_func_case
(
List
<
Item
>
&
list
,
Item
*
first_expr_arg
,
Item
*
else_expr_arg
)
:
Item_func
(),
first_expr_num
(
-
1
),
else_expr_num
(
-
1
),
cached_result_type
(
INT_RESULT
),
left_result_type
(
INT_RESULT
),
case_item
(
0
)
{
ncases
=
list
.
elements
;
if
(
first_expr_arg
)
{
first_expr_num
=
list
.
elements
;
list
.
push_back
(
first_expr_arg
);
}
if
(
else_expr_arg
)
{
else_expr_num
=
list
.
elements
;
list
.
push_back
(
else_expr_arg
);
}
set_arguments
(
list
);
bzero
(
&
cmp_items
,
sizeof
(
cmp_items
));
}
double
val_real
();
longlong
val_int
();
String
*
val_str
(
String
*
);
my_decimal
*
val_decimal
(
my_decimal
*
);
bool
fix_fields
(
THD
*
thd
,
Item
**
ref
);
void
fix_length_and_dec
();
uint
decimal_precision
()
const
;
table_map
not_null_tables
()
const
{
return
0
;
}
enum
Item_result
result_type
()
const
{
return
cached_result_type
;
}
const
char
*
func_name
()
const
{
return
"case"
;
}
void
print
(
String
*
str
);
Item
*
find_item
(
String
*
str
);
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
bool
check_partition_func_processor
(
byte
*
bool_arg
)
{
return
0
;}
void
cleanup
()
{
uint
i
;
DBUG_ENTER
(
"Item_func_case::cleanup"
);
Item_func
::
cleanup
();
for
(
i
=
0
;
i
<=
(
uint
)
DECIMAL_RESULT
;
i
++
)
{
delete
cmp_items
[
i
];
cmp_items
[
i
]
=
0
;
}
DBUG_VOID_RETURN
;
}
};
/*
The Item_func_in class implements the in_expr IN(values_list) function.
The current implementation distinguishes 2 cases:
1) all items in the value_list are constants and have the same
result type. This case is handled by in_vector class.
2) items in the value_list have different result types or there is some
non-constant items.
In this case Item_func_in employs several cmp_item objects to performs
comparisons of in_expr and an item from the values_list. One cmp_item
object for each result type. Different result types are collected in the
fix_length_and_dec() member function by means of collect_cmp_types()
function.
*/
class
Item_func_in
:
public
Item_func_opt_neg
class
Item_func_in
:
public
Item_func_opt_neg
{
{
public:
public:
Item_result
cmp_type
;
in_vector
*
array
;
in_vector
*
array
;
cmp_item
*
in_item
;
bool
have_null
;
bool
have_null
;
Item_result
left_result_type
;
cmp_item
*
cmp_items
[
5
];
/* One cmp_item for each result type */
DTCollation
cmp_collation
;
DTCollation
cmp_collation
;
Item_func_in
(
List
<
Item
>
&
list
)
Item_func_in
(
List
<
Item
>
&
list
)
:
Item_func_opt_neg
(
list
),
array
(
0
),
in_item
(
0
),
have_null
(
0
)
:
Item_func_opt_neg
(
list
),
array
(
0
),
have_null
(
0
)
{
{
bzero
(
&
cmp_items
,
sizeof
(
cmp_items
));
allowed_arg_cols
=
0
;
// Fetch this value from first argument
allowed_arg_cols
=
0
;
// Fetch this value from first argument
}
}
longlong
val_int
();
longlong
val_int
();
...
@@ -963,12 +1027,16 @@ class Item_func_in :public Item_func_opt_neg
...
@@ -963,12 +1027,16 @@ class Item_func_in :public Item_func_opt_neg
uint
decimal_precision
()
const
{
return
1
;
}
uint
decimal_precision
()
const
{
return
1
;
}
void
cleanup
()
void
cleanup
()
{
{
uint
i
;
DBUG_ENTER
(
"Item_func_in::cleanup"
);
DBUG_ENTER
(
"Item_func_in::cleanup"
);
Item_int_func
::
cleanup
();
Item_int_func
::
cleanup
();
delete
array
;
delete
array
;
delete
in_item
;
array
=
0
;
array
=
0
;
in_item
=
0
;
for
(
i
=
0
;
i
<=
(
uint
)
DECIMAL_RESULT
;
i
++
)
{
delete
cmp_items
[
i
];
cmp_items
[
i
]
=
0
;
}
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
optimize_type
select_optimize
()
const
optimize_type
select_optimize
()
const
...
...
sql/opt_range.cc
View file @
7a84e124
...
@@ -4913,9 +4913,17 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
...
@@ -4913,9 +4913,17 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
{
{
Item_func_in
*
func
=
(
Item_func_in
*
)
cond_func
;
Item_func_in
*
func
=
(
Item_func_in
*
)
cond_func
;
/*
Array for IN() is constructed when all values have the same result
type. Tree won't be built for values with different result types,
so we check it here to avoid unnecessary work.
*/
if
(
!
func
->
array
)
break
;
if
(
inv
)
if
(
inv
)
{
{
if
(
func
->
array
&&
func
->
cmp_type
!=
ROW_RESULT
)
if
(
func
->
array
->
result_type
()
!=
ROW_RESULT
)
{
{
/*
/*
We get here for conditions in form "t.key NOT IN (c1, c2, ...)",
We get here for conditions in form "t.key NOT IN (c1, c2, ...)",
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment