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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
6ff3befd
Commit
6ff3befd
authored
Sep 07, 2005
by
aivanov@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge mysql.com:/home/alexi/mysql-4.1
into mysql.com:/home/alexi/dev/mysql-4.1-0
parents
a0ddff9c
fa51afed
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
397 additions
and
32 deletions
+397
-32
mysql-test/r/join_outer.result
mysql-test/r/join_outer.result
+133
-0
mysql-test/t/join_outer.test
mysql-test/t/join_outer.test
+46
-0
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+150
-8
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+38
-17
sql/opt_range.cc
sql/opt_range.cc
+3
-2
sql/sql_yacc.yy
sql/sql_yacc.yy
+27
-5
No files found.
mysql-test/r/join_outer.result
View file @
6ff3befd
...
@@ -883,3 +883,136 @@ Warnings:
...
@@ -883,3 +883,136 @@ Warnings:
Warning 1260 2 line(s) were cut by GROUP_CONCAT()
Warning 1260 2 line(s) were cut by GROUP_CONCAT()
drop table t1, t2;
drop table t1, t2;
set group_concat_max_len=default;
set group_concat_max_len=default;
CREATE TABLE t1 (a int PRIMARY KEY, b int);
CREATE TABLE t2 (a int PRIMARY KEY, b int);
INSERT INTO t1 VALUES (1,2), (2,1), (3,2), (4,3), (5,6), (6,5), (7,8), (8,7), (9,10);
INSERT INTO t2 VALUES (3,0), (4,1), (6,4), (7,5);
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b <= t1.a AND t1.a <= t1.b;
a b a b
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a BETWEEN t2.b AND t1.b;
a b a b
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT BETWEEN t2.b AND t1.b);
a b a b
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.b > t1.a OR t1.a > t1.b;
a b a b
2 1 NULL NULL
3 2 3 0
4 3 4 1
6 5 6 4
8 7 NULL NULL
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT BETWEEN t2.b AND t1.b;
a b a b
2 1 NULL NULL
3 2 3 0
4 3 4 1
6 5 6 4
8 7 NULL NULL
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a BETWEEN t2.b AND t1.b);
a b a b
2 1 NULL NULL
3 2 3 0
4 3 4 1
6 5 6 4
8 7 NULL NULL
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t2.b > t1.a OR t1.a > t1.b;
a b a b
2 1 NULL NULL
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
8 7 NULL NULL
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a AND t1.a BETWEEN t2.b AND t1.b);
a b a b
2 1 NULL NULL
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
8 7 NULL NULL
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a AND (t2.b > t1.a OR t1.a > t1.b);
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a != t2.a OR t1.a BETWEEN t2.b AND t1.b);
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a NOT IN(t2.a, t2.b));
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a != t1.b AND t1.a != t2.b;
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a NOT IN(t1.b, t2.b);
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t1.a IN(t1.b, t2.b));
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b OR (t1.a != t2.a AND t1.a != t2.b);
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b AND t1.a IN(t2.a, t2.b));
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t2.a != t2.b AND t1.a != t1.b AND t1.a != t2.b;
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE NOT(t2.a = t2.b OR t1.a IN(t1.b, t2.b));
a b a b
3 2 3 0
4 3 4 1
6 5 6 4
7 8 7 5
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a > IF(t1.a = t2.b-2, t2.b, t2.b-1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 Using where
DROP TABLE t1,t2;
mysql-test/t/join_outer.test
View file @
6ff3befd
...
@@ -625,4 +625,50 @@ select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a;
...
@@ -625,4 +625,50 @@ select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a;
drop
table
t1
,
t2
;
drop
table
t1
,
t2
;
set
group_concat_max_len
=
default
;
set
group_concat_max_len
=
default
;
#
# Test for bugs
# #12101: erroneously applied outer join elimination in case of WHERE NOT BETWEEN
# #12102: erroneously missing outer join elimination in case of WHERE IN/IF
#
CREATE
TABLE
t1
(
a
int
PRIMARY
KEY
,
b
int
);
CREATE
TABLE
t2
(
a
int
PRIMARY
KEY
,
b
int
);
INSERT
INTO
t1
VALUES
(
1
,
2
),
(
2
,
1
),
(
3
,
2
),
(
4
,
3
),
(
5
,
6
),
(
6
,
5
),
(
7
,
8
),
(
8
,
7
),
(
9
,
10
);
INSERT
INTO
t2
VALUES
(
3
,
0
),
(
4
,
1
),
(
6
,
4
),
(
7
,
5
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t2
.
b
<=
t1
.
a
AND
t1
.
a
<=
t1
.
b
;
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
BETWEEN
t2
.
b
AND
t1
.
b
;
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
NOT
(
t1
.
a
NOT
BETWEEN
t2
.
b
AND
t1
.
b
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t2
.
b
>
t1
.
a
OR
t1
.
a
>
t1
.
b
;
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
NOT
BETWEEN
t2
.
b
AND
t1
.
b
;
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
NOT
(
t1
.
a
BETWEEN
t2
.
b
AND
t1
.
b
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
=
t2
.
a
OR
t2
.
b
>
t1
.
a
OR
t1
.
a
>
t1
.
b
;
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
NOT
(
t1
.
a
!=
t2
.
a
AND
t1
.
a
BETWEEN
t2
.
b
AND
t1
.
b
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
=
t2
.
a
AND
(
t2
.
b
>
t1
.
a
OR
t1
.
a
>
t1
.
b
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
NOT
(
t1
.
a
!=
t2
.
a
OR
t1
.
a
BETWEEN
t2
.
b
AND
t1
.
b
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
=
t2
.
a
OR
t1
.
a
=
t2
.
b
;
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
IN
(
t2
.
a
,
t2
.
b
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
NOT
(
t1
.
a
NOT
IN
(
t2
.
a
,
t2
.
b
));
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
!=
t1
.
b
AND
t1
.
a
!=
t2
.
b
;
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
NOT
IN
(
t1
.
b
,
t2
.
b
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
NOT
(
t1
.
a
IN
(
t1
.
b
,
t2
.
b
));
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t2
.
a
!=
t2
.
b
OR
(
t1
.
a
!=
t2
.
a
AND
t1
.
a
!=
t2
.
b
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
NOT
(
t2
.
a
=
t2
.
b
AND
t1
.
a
IN
(
t2
.
a
,
t2
.
b
));
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t2
.
a
!=
t2
.
b
AND
t1
.
a
!=
t1
.
b
AND
t1
.
a
!=
t2
.
b
;
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
NOT
(
t2
.
a
=
t2
.
b
OR
t1
.
a
IN
(
t1
.
b
,
t2
.
b
));
EXPLAIN
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
=
t2
.
a
OR
t1
.
a
=
t2
.
b
;
EXPLAIN
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
IN
(
t2
.
a
,
t2
.
b
);
EXPLAIN
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
t1
.
a
=
t2
.
a
WHERE
t1
.
a
>
IF
(
t1
.
a
=
t2
.
b
-
2
,
t2
.
b
,
t2
.
b
-
1
);
DROP
TABLE
t1
,
t2
;
# End of 4.1 tests
# End of 4.1 tests
sql/item_cmpfunc.cc
View file @
6ff3befd
...
@@ -820,6 +820,54 @@ longlong Item_func_interval::val_int()
...
@@ -820,6 +820,54 @@ longlong Item_func_interval::val_int()
return
i
-
1
;
return
i
-
1
;
}
}
/*
Perform context analysis of a BETWEEN item tree
SYNOPSIS:
fix_fields()
thd reference to the global context of the query thread
tables list of all open tables involved in the query
ref pointer to Item* variable where pointer to resulting "fixed"
item is to be assigned
DESCRIPTION
This function performs context analysis (name resolution) and calculates
various attributes of the item tree with Item_func_between as its root.
The function saves in ref the pointer to the item or to a newly created
item that is considered as a replacement for the original one.
NOTES
Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
a predicate/function level. Then it's easy to show that:
T0(e BETWEEN e1 AND e2) = union(T1(e),T1(e1),T1(e2))
T1(e BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
T0(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
T1(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
RETURN
0 ok
1 got error
*/
bool
Item_func_between
::
fix_fields
(
THD
*
thd
,
struct
st_table_list
*
tables
,
Item
**
ref
)
{
if
(
Item_func_opt_neg
::
fix_fields
(
thd
,
tables
,
ref
))
return
1
;
/* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
if
(
pred_level
&&
!
negated
)
return
0
;
/* not_null_tables_cache == union(T1(e), intersection(T1(e1),T1(e2))) */
not_null_tables_cache
=
args
[
0
]
->
not_null_tables
()
|
(
args
[
1
]
->
not_null_tables
()
&
args
[
2
]
->
not_null_tables
());
return
0
;
}
void
Item_func_between
::
fix_length_and_dec
()
void
Item_func_between
::
fix_length_and_dec
()
{
{
max_length
=
1
;
max_length
=
1
;
...
@@ -871,8 +919,9 @@ longlong Item_func_between::val_int()
...
@@ -871,8 +919,9 @@ longlong Item_func_between::val_int()
a
=
args
[
1
]
->
val_str
(
&
value1
);
a
=
args
[
1
]
->
val_str
(
&
value1
);
b
=
args
[
2
]
->
val_str
(
&
value2
);
b
=
args
[
2
]
->
val_str
(
&
value2
);
if
(
!
args
[
1
]
->
null_value
&&
!
args
[
2
]
->
null_value
)
if
(
!
args
[
1
]
->
null_value
&&
!
args
[
2
]
->
null_value
)
return
(
sortcmp
(
value
,
a
,
cmp_collation
.
collation
)
>=
0
&&
return
(
longlong
)
((
sortcmp
(
value
,
a
,
cmp_collation
.
collation
)
>=
0
&&
sortcmp
(
value
,
b
,
cmp_collation
.
collation
)
<=
0
)
?
1
:
0
;
sortcmp
(
value
,
b
,
cmp_collation
.
collation
)
<=
0
)
!=
negated
);
if
(
args
[
1
]
->
null_value
&&
args
[
2
]
->
null_value
)
if
(
args
[
1
]
->
null_value
&&
args
[
2
]
->
null_value
)
null_value
=
1
;
null_value
=
1
;
else
if
(
args
[
1
]
->
null_value
)
else
if
(
args
[
1
]
->
null_value
)
...
@@ -894,7 +943,7 @@ longlong Item_func_between::val_int()
...
@@ -894,7 +943,7 @@ longlong Item_func_between::val_int()
a
=
args
[
1
]
->
val_int
();
a
=
args
[
1
]
->
val_int
();
b
=
args
[
2
]
->
val_int
();
b
=
args
[
2
]
->
val_int
();
if
(
!
args
[
1
]
->
null_value
&&
!
args
[
2
]
->
null_value
)
if
(
!
args
[
1
]
->
null_value
&&
!
args
[
2
]
->
null_value
)
return
(
value
>=
a
&&
value
<=
b
)
?
1
:
0
;
return
(
longlong
)
((
value
>=
a
&&
value
<=
b
)
!=
negated
)
;
if
(
args
[
1
]
->
null_value
&&
args
[
2
]
->
null_value
)
if
(
args
[
1
]
->
null_value
&&
args
[
2
]
->
null_value
)
null_value
=
1
;
null_value
=
1
;
else
if
(
args
[
1
]
->
null_value
)
else
if
(
args
[
1
]
->
null_value
)
...
@@ -914,7 +963,7 @@ longlong Item_func_between::val_int()
...
@@ -914,7 +963,7 @@ longlong Item_func_between::val_int()
a
=
args
[
1
]
->
val
();
a
=
args
[
1
]
->
val
();
b
=
args
[
2
]
->
val
();
b
=
args
[
2
]
->
val
();
if
(
!
args
[
1
]
->
null_value
&&
!
args
[
2
]
->
null_value
)
if
(
!
args
[
1
]
->
null_value
&&
!
args
[
2
]
->
null_value
)
return
(
value
>=
a
&&
value
<=
b
)
?
1
:
0
;
return
(
longlong
)
((
value
>=
a
&&
value
<=
b
)
!=
negated
)
;
if
(
args
[
1
]
->
null_value
&&
args
[
2
]
->
null_value
)
if
(
args
[
1
]
->
null_value
&&
args
[
2
]
->
null_value
)
null_value
=
1
;
null_value
=
1
;
else
if
(
args
[
1
]
->
null_value
)
else
if
(
args
[
1
]
->
null_value
)
...
@@ -926,7 +975,7 @@ longlong Item_func_between::val_int()
...
@@ -926,7 +975,7 @@ longlong Item_func_between::val_int()
null_value
=
value
>=
a
;
null_value
=
value
>=
a
;
}
}
}
}
return
0
;
return
(
longlong
)
(
!
null_value
&&
negated
)
;
}
}
...
@@ -1019,6 +1068,49 @@ Item_func_ifnull::val_str(String *str)
...
@@ -1019,6 +1068,49 @@ Item_func_ifnull::val_str(String *str)
}
}
/*
Perform context analysis of an IF item tree
SYNOPSIS:
fix_fields()
thd reference to the global context of the query thread
tables list of all open tables involved in the query
ref pointer to Item* variable where pointer to resulting "fixed"
item is to be assigned
DESCRIPTION
This function performs context analysis (name resolution) and calculates
various attributes of the item tree with Item_func_if as its root.
The function saves in ref the pointer to the item or to a newly created
item that is considered as a replacement for the original one.
NOTES
Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
a predicate/function level. Then it's easy to show that:
T0(IF(e,e1,e2) = T1(IF(e,e1,e2))
T1(IF(e,e1,e2)) = intersection(T1(e1),T1(e2))
RETURN
0 ok
1 got error
*/
bool
Item_func_if
::
fix_fields
(
THD
*
thd
,
struct
st_table_list
*
tlist
,
Item
**
ref
)
{
DBUG_ASSERT
(
fixed
==
0
);
args
[
0
]
->
top_level_item
();
if
(
Item_func
::
fix_fields
(
thd
,
tlist
,
ref
))
return
1
;
not_null_tables_cache
=
(
args
[
1
]
->
not_null_tables
()
&
args
[
2
]
->
not_null_tables
());
return
0
;
}
void
void
Item_func_if
::
fix_length_and_dec
()
Item_func_if
::
fix_length_and_dec
()
{
{
...
@@ -1750,6 +1842,56 @@ bool Item_func_in::nulls_in_row()
...
@@ -1750,6 +1842,56 @@ bool Item_func_in::nulls_in_row()
}
}
/*
Perform context analysis of an IN item tree
SYNOPSIS:
fix_fields()
thd reference to the global context of the query thread
tables list of all open tables involved in the query
ref pointer to Item* variable where pointer to resulting "fixed"
item is to be assigned
DESCRIPTION
This function performs context analysis (name resolution) and calculates
various attributes of the item tree with Item_func_in as its root.
The function saves in ref the pointer to the item or to a newly created
item that is considered as a replacement for the original one.
NOTES
Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
a predicate/function level. Then it's easy to show that:
T0(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))
T1(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))
T0(e NOT IN(e1,...,en)) = union(T1(e),union(T1(ei)))
T1(e NOT IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))
RETURN
0 ok
1 got error
*/
bool
Item_func_in
::
fix_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
,
Item
**
ref
)
{
Item
**
arg
,
**
arg_end
;
if
(
Item_func_opt_neg
::
fix_fields
(
thd
,
tables
,
ref
))
return
1
;
/* not_null_tables_cache == union(T1(e),union(T1(ei))) */
if
(
pred_level
&&
negated
)
return
0
;
/* not_null_tables_cache = union(T1(e),intersection(T1(ei))) */
not_null_tables_cache
=
~
(
table_map
)
0
;
for
(
arg
=
args
+
1
,
arg_end
=
args
+
arg_count
;
arg
!=
arg_end
;
arg
++
)
not_null_tables_cache
&=
(
*
arg
)
->
not_null_tables
();
not_null_tables_cache
|=
(
*
args
)
->
not_null_tables
();
return
0
;
}
static
int
srtcmp_in
(
CHARSET_INFO
*
cs
,
const
String
*
x
,
const
String
*
y
)
static
int
srtcmp_in
(
CHARSET_INFO
*
cs
,
const
String
*
x
,
const
String
*
y
)
{
{
return
cs
->
coll
->
strnncollsp
(
cs
,
return
cs
->
coll
->
strnncollsp
(
cs
,
...
@@ -1840,7 +1982,7 @@ longlong Item_func_in::val_int()
...
@@ -1840,7 +1982,7 @@ longlong Item_func_in::val_int()
{
{
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
tmp
;
return
(
longlong
)
(
!
null_value
&&
tmp
!=
negated
)
;
}
}
in_item
->
store_value
(
args
[
0
]);
in_item
->
store_value
(
args
[
0
]);
if
((
null_value
=
args
[
0
]
->
null_value
))
if
((
null_value
=
args
[
0
]
->
null_value
))
...
@@ -1849,11 +1991,11 @@ longlong Item_func_in::val_int()
...
@@ -1849,11 +1991,11 @@ longlong Item_func_in::val_int()
for
(
uint
i
=
1
;
i
<
arg_count
;
i
++
)
for
(
uint
i
=
1
;
i
<
arg_count
;
i
++
)
{
{
if
(
!
in_item
->
cmp
(
args
[
i
])
&&
!
args
[
i
]
->
null_value
)
if
(
!
in_item
->
cmp
(
args
[
i
])
&&
!
args
[
i
]
->
null_value
)
return
1
;
// Would maybe be nice with i ?
return
(
longlong
)
(
!
negated
);
have_null
|=
args
[
i
]
->
null_value
;
have_null
|=
args
[
i
]
->
null_value
;
}
}
null_value
=
have_null
;
null_value
=
have_null
;
return
0
;
return
(
longlong
)
(
!
null_value
&&
negated
)
;
}
}
...
...
sql/item_cmpfunc.h
View file @
6ff3befd
...
@@ -358,17 +358,49 @@ public:
...
@@ -358,17 +358,49 @@ public:
};
};
class
Item_func_between
:
public
Item_int_func
/*
The class Item_func_opt_neg is defined to factor out the functionality
common for the classes Item_func_between and Item_func_in. The objects
of these classes can express predicates or there negations.
The alternative approach would be to create pairs Item_func_between,
Item_func_notbetween and Item_func_in, Item_func_notin.
*/
class
Item_func_opt_neg
:
public
Item_int_func
{
public:
bool
negated
;
/* <=> the item represents NOT <func> */
bool
pred_level
;
/* <=> [NOT] <func> is used on a predicate level */
public:
Item_func_opt_neg
(
Item
*
a
,
Item
*
b
,
Item
*
c
)
:
Item_int_func
(
a
,
b
,
c
),
negated
(
0
),
pred_level
(
0
)
{}
Item_func_opt_neg
(
List
<
Item
>
&
list
)
:
Item_int_func
(
list
),
negated
(
0
),
pred_level
(
0
)
{}
public:
inline
void
negate
()
{
negated
=
!
negated
;
}
inline
void
top_level_item
()
{
pred_level
=
1
;
}
Item
*
neg_transformer
(
THD
*
thd
)
{
negated
=
!
negated
;
return
this
;
}
};
class
Item_func_between
:
public
Item_func_opt_neg
{
{
DTCollation
cmp_collation
;
DTCollation
cmp_collation
;
public:
public:
Item_result
cmp_type
;
Item_result
cmp_type
;
String
value0
,
value1
,
value2
;
String
value0
,
value1
,
value2
;
Item_func_between
(
Item
*
a
,
Item
*
b
,
Item
*
c
)
:
Item_int_func
(
a
,
b
,
c
)
{}
Item_func_between
(
Item
*
a
,
Item
*
b
,
Item
*
c
)
:
Item_func_opt_neg
(
a
,
b
,
c
)
{}
longlong
val_int
();
longlong
val_int
();
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_KEY
;
}
optimize_type
select_optimize
()
const
{
return
OPTIMIZE_KEY
;
}
enum
Functype
functype
()
const
{
return
BETWEEN
;
}
enum
Functype
functype
()
const
{
return
BETWEEN
;
}
const
char
*
func_name
()
const
{
return
"between"
;
}
const
char
*
func_name
()
const
{
return
"between"
;
}
bool
fix_fields
(
THD
*
,
struct
st_table_list
*
,
Item
**
);
void
fix_length_and_dec
();
void
fix_length_and_dec
();
void
print
(
String
*
str
);
void
print
(
String
*
str
);
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
...
@@ -433,15 +465,9 @@ public:
...
@@ -433,15 +465,9 @@ public:
longlong
val_int
();
longlong
val_int
();
String
*
val_str
(
String
*
str
);
String
*
val_str
(
String
*
str
);
enum
Item_result
result_type
()
const
{
return
cached_result_type
;
}
enum
Item_result
result_type
()
const
{
return
cached_result_type
;
}
bool
fix_fields
(
THD
*
thd
,
struct
st_table_list
*
tlist
,
Item
**
ref
)
bool
fix_fields
(
THD
*
,
struct
st_table_list
*
,
Item
**
);
{
DBUG_ASSERT
(
fixed
==
0
);
args
[
0
]
->
top_level_item
();
return
Item_func
::
fix_fields
(
thd
,
tlist
,
ref
);
}
void
fix_length_and_dec
();
void
fix_length_and_dec
();
const
char
*
func_name
()
const
{
return
"if"
;
}
const
char
*
func_name
()
const
{
return
"if"
;
}
table_map
not_null_tables
()
const
{
return
0
;
}
};
};
...
@@ -736,7 +762,7 @@ public:
...
@@ -736,7 +762,7 @@ public:
}
}
};
};
class
Item_func_in
:
public
Item_
int_func
class
Item_func_in
:
public
Item_
func_opt_neg
{
{
Item_result
cmp_type
;
Item_result
cmp_type
;
in_vector
*
array
;
in_vector
*
array
;
...
@@ -745,11 +771,12 @@ class Item_func_in :public Item_int_func
...
@@ -745,11 +771,12 @@ class Item_func_in :public Item_int_func
DTCollation
cmp_collation
;
DTCollation
cmp_collation
;
public:
public:
Item_func_in
(
List
<
Item
>
&
list
)
Item_func_in
(
List
<
Item
>
&
list
)
:
Item_
int_func
(
list
),
array
(
0
),
in_item
(
0
),
have_null
(
0
)
:
Item_
func_opt_neg
(
list
),
array
(
0
),
in_item
(
0
),
have_null
(
0
)
{
{
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
();
bool
fix_fields
(
THD
*
,
struct
st_table_list
*
,
Item
**
);
void
fix_length_and_dec
();
void
fix_length_and_dec
();
void
cleanup
()
void
cleanup
()
{
{
...
@@ -769,12 +796,6 @@ class Item_func_in :public Item_int_func
...
@@ -769,12 +796,6 @@ class Item_func_in :public Item_int_func
bool
nulls_in_row
();
bool
nulls_in_row
();
bool
is_bool_func
()
{
return
1
;
}
bool
is_bool_func
()
{
return
1
;
}
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
CHARSET_INFO
*
compare_collation
()
{
return
cmp_collation
.
collation
;
}
/*
IN() protect from NULL only first argument, if construction like
"expression IN ()" will be allowed, we will need to check number of
argument here, because "NOT(NULL IN ())" is TRUE.
*/
table_map
not_null_tables
()
const
{
return
args
[
0
]
->
not_null_tables
();
}
};
};
/* Functions used by where clause */
/* Functions used by where clause */
...
...
sql/opt_range.cc
View file @
6ff3befd
...
@@ -849,7 +849,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
...
@@ -849,7 +849,8 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
if
(
cond_func
->
functype
()
==
Item_func
::
BETWEEN
)
if
(
cond_func
->
functype
()
==
Item_func
::
BETWEEN
)
{
{
if
(
cond_func
->
arguments
()[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
if
(
!
((
Item_func_between
*
)(
cond_func
))
->
negated
&&
cond_func
->
arguments
()[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
{
{
Field
*
field
=
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
]))
->
field
;
Field
*
field
=
((
Item_field
*
)
(
cond_func
->
arguments
()[
0
]))
->
field
;
Item_result
cmp_type
=
field
->
cmp_type
();
Item_result
cmp_type
=
field
->
cmp_type
();
...
@@ -866,7 +867,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
...
@@ -866,7 +867,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
if
(
cond_func
->
functype
()
==
Item_func
::
IN_FUNC
)
if
(
cond_func
->
functype
()
==
Item_func
::
IN_FUNC
)
{
// COND OR
{
// COND OR
Item_func_in
*
func
=
(
Item_func_in
*
)
cond_func
;
Item_func_in
*
func
=
(
Item_func_in
*
)
cond_func
;
if
(
func
->
key_item
()
->
type
()
==
Item
::
FIELD_ITEM
)
if
(
!
func
->
negated
&&
func
->
key_item
()
->
type
()
==
Item
::
FIELD_ITEM
)
{
{
Field
*
field
=
((
Item_field
*
)
(
func
->
key_item
()))
->
field
;
Field
*
field
=
((
Item_field
*
)
(
func
->
key_item
()))
->
field
;
Item_result
cmp_type
=
field
->
cmp_type
();
Item_result
cmp_type
=
field
->
cmp_type
();
...
...
sql/sql_yacc.yy
View file @
6ff3befd
...
@@ -2598,7 +2598,12 @@ expr_expr:
...
@@ -2598,7 +2598,12 @@ expr_expr:
expr IN_SYM '(' expr_list ')'
expr IN_SYM '(' expr_list ')'
{ $4->push_front($1); $$= new Item_func_in(*$4); }
{ $4->push_front($1); $$= new Item_func_in(*$4); }
| expr NOT IN_SYM '(' expr_list ')'
| expr NOT IN_SYM '(' expr_list ')'
{ $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
{
$5->push_front($1);
Item_func_in *item= new Item_func_in(*$5);
item->negate();
$$= item;
}
| expr IN_SYM in_subselect
| expr IN_SYM in_subselect
{ $$= new Item_in_subselect($1, $3); }
{ $$= new Item_in_subselect($1, $3); }
| expr NOT IN_SYM in_subselect
| expr NOT IN_SYM in_subselect
...
@@ -2608,7 +2613,11 @@ expr_expr:
...
@@ -2608,7 +2613,11 @@ expr_expr:
| expr BETWEEN_SYM no_and_expr AND_SYM expr
| expr BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_between($1,$3,$5); }
{ $$= new Item_func_between($1,$3,$5); }
| expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
| expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
{
Item_func_between *item= new Item_func_between($1,$4,$6);
item->negate();
$$= item;
}
| expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| expr XOR expr { $$= new Item_cond_xor($1,$3); }
| expr XOR expr { $$= new Item_cond_xor($1,$3); }
...
@@ -2656,7 +2665,11 @@ no_in_expr:
...
@@ -2656,7 +2665,11 @@ no_in_expr:
no_in_expr BETWEEN_SYM no_and_expr AND_SYM expr
no_in_expr BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_between($1,$3,$5); }
{ $$= new Item_func_between($1,$3,$5); }
| no_in_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
| no_in_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
{
Item_func_between *item= new Item_func_between($1,$4,$6);
item->negate();
$$= item;
}
| no_in_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_in_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_in_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| no_in_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
...
@@ -2704,7 +2717,12 @@ no_and_expr:
...
@@ -2704,7 +2717,12 @@ no_and_expr:
no_and_expr IN_SYM '(' expr_list ')'
no_and_expr IN_SYM '(' expr_list ')'
{ $4->push_front($1); $$= new Item_func_in(*$4); }
{ $4->push_front($1); $$= new Item_func_in(*$4); }
| no_and_expr NOT IN_SYM '(' expr_list ')'
| no_and_expr NOT IN_SYM '(' expr_list ')'
{ $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
{
$5->push_front($1);
Item_func_in *item= new Item_func_in(*$5);
item->negate();
$$= item;
}
| no_and_expr IN_SYM in_subselect
| no_and_expr IN_SYM in_subselect
{ $$= new Item_in_subselect($1, $3); }
{ $$= new Item_in_subselect($1, $3); }
| no_and_expr NOT IN_SYM in_subselect
| no_and_expr NOT IN_SYM in_subselect
...
@@ -2714,7 +2732,11 @@ no_and_expr:
...
@@ -2714,7 +2732,11 @@ no_and_expr:
| no_and_expr BETWEEN_SYM no_and_expr AND_SYM expr
| no_and_expr BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_between($1,$3,$5); }
{ $$= new Item_func_between($1,$3,$5); }
| no_and_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
| no_and_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
{ $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
{
Item_func_between *item= new Item_func_between($1,$4,$6);
item->negate();
$$= item;
}
| no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_and_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| no_and_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
| no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
...
...
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