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
d6398c1a
Commit
d6398c1a
authored
Sep 07, 2005
by
aivanov@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge mysql.com:/home/alexi/mysql-5.0
into mysql.com:/home/alexi/dev/mysql-5.0-0
parents
d261e1f5
4b245a28
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
381 additions
and
57 deletions
+381
-57
BitKeeper/etc/RESYNC_TREE
BitKeeper/etc/RESYNC_TREE
+0
-0
mysql-test/r/join_outer.result
mysql-test/r/join_outer.result
+134
-1
mysql-test/t/join_outer.test
mysql-test/t/join_outer.test
+47
-2
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+151
-10
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+38
-17
sql/opt_range.cc
sql/opt_range.cc
+3
-12
sql/sql_select.cc
sql/sql_select.cc
+0
-13
sql/sql_yacc.yy
sql/sql_yacc.yy
+8
-2
No files found.
BitKeeper/etc/RESYNC_TREE
0 → 100644
View file @
d6398c1a
mysql-test/r/join_outer.result
View file @
d6398c1a
...
@@ -200,7 +200,7 @@ INSERT INTO t1 VALUES (10363,'Tecniques de Comunicacio Oral i Escrita','Tecnicas
...
@@ -200,7 +200,7 @@ INSERT INTO t1 VALUES (10363,'Tecniques de Comunicacio Oral i Escrita','Tecnicas
INSERT INTO t1 VALUES (11403,'Projecte Fi de Carrera','Proyecto Fin de Carrera','Projecte Fi de Carrera','PFC',9.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11403,'Projecte Fi de Carrera','Proyecto Fin de Carrera','Projecte Fi de Carrera','PFC',9.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11404,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',15.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11404,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',15.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11405,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',18.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11405,'+lgebra lineal','Algebra lineal','+lgebra lineal','+lgebra lineal',18.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','C
l
culo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
INSERT INTO t1 VALUES (11406,'Calcul Infinitesimal','C
ßl
culo Infinitesimal','Calcul Infinitesimal','Calcul Infinitesimal',15.0,NULL,NULL,NULL);
CREATE TABLE t2 (
CREATE TABLE t2 (
idAssignatura int(11) DEFAULT '0' NOT NULL,
idAssignatura int(11) DEFAULT '0' NOT NULL,
Grup int(11) DEFAULT '0' NOT NULL,
Grup int(11) DEFAULT '0' NOT NULL,
...
@@ -1001,3 +1001,136 @@ SELECT * FROM t1 LEFT JOIN t2 ON (c11=c21 AND c21=30) WHERE c11=40;
...
@@ -1001,3 +1001,136 @@ SELECT * FROM t1 LEFT JOIN t2 ON (c11=c21 AND c21=30) WHERE c11=40;
c11 c21
c11 c21
40 NULL
40 NULL
DROP TABLE t1, t2;
DROP TABLE t1, t2;
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 Using where
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 Using where
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 > 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 Using where
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1
DROP TABLE t1,t2;
mysql-test/t/join_outer.test
View file @
d6398c1a
...
@@ -135,7 +135,7 @@ INSERT INTO t1 VALUES (10363,'Tecniques de Comunicacio Oral i Escrita','Tecnicas
...
@@ -135,7 +135,7 @@ INSERT INTO t1 VALUES (10363,'Tecniques de Comunicacio Oral i Escrita','Tecnicas
INSERT
INTO
t1
VALUES
(
11403
,
'Projecte Fi de Carrera'
,
'Proyecto Fin de Carrera'
,
'Projecte Fi de Carrera'
,
'PFC'
,
9.0
,
NULL
,
NULL
,
NULL
);
INSERT
INTO
t1
VALUES
(
11403
,
'Projecte Fi de Carrera'
,
'Proyecto Fin de Carrera'
,
'Projecte Fi de Carrera'
,
'PFC'
,
9.0
,
NULL
,
NULL
,
NULL
);
INSERT
INTO
t1
VALUES
(
11404
,
'+lgebra lineal'
,
'Algebra lineal'
,
'+lgebra lineal'
,
'+lgebra lineal'
,
15.0
,
NULL
,
NULL
,
NULL
);
INSERT
INTO
t1
VALUES
(
11404
,
'+lgebra lineal'
,
'Algebra lineal'
,
'+lgebra lineal'
,
'+lgebra lineal'
,
15.0
,
NULL
,
NULL
,
NULL
);
INSERT
INTO
t1
VALUES
(
11405
,
'+lgebra lineal'
,
'Algebra lineal'
,
'+lgebra lineal'
,
'+lgebra lineal'
,
18.0
,
NULL
,
NULL
,
NULL
);
INSERT
INTO
t1
VALUES
(
11405
,
'+lgebra lineal'
,
'Algebra lineal'
,
'+lgebra lineal'
,
'+lgebra lineal'
,
18.0
,
NULL
,
NULL
,
NULL
);
INSERT
INTO
t1
VALUES
(
11406
,
'Calcul Infinitesimal'
,
'C
l
culo Infinitesimal'
,
'Calcul Infinitesimal'
,
'Calcul Infinitesimal'
,
15.0
,
NULL
,
NULL
,
NULL
);
INSERT
INTO
t1
VALUES
(
11406
,
'Calcul Infinitesimal'
,
'C
ßl
culo Infinitesimal'
,
'Calcul Infinitesimal'
,
'Calcul Infinitesimal'
,
15.0
,
NULL
,
NULL
,
NULL
);
CREATE
TABLE
t2
(
CREATE
TABLE
t2
(
idAssignatura
int
(
11
)
DEFAULT
'0'
NOT
NULL
,
idAssignatura
int
(
11
)
DEFAULT
'0'
NOT
NULL
,
...
@@ -590,7 +590,6 @@ INSERT INTO t2 VALUES("0", "EN", "0-EN");
...
@@ -590,7 +590,6 @@ INSERT INTO t2 VALUES("0", "EN", "0-EN");
INSERT
INTO
t2
VALUES
(
"0"
,
"SV"
,
"0-SV"
);
INSERT
INTO
t2
VALUES
(
"0"
,
"SV"
,
"0-SV"
);
INSERT
INTO
t2
VALUES
(
"10"
,
"EN"
,
"10-EN"
);
INSERT
INTO
t2
VALUES
(
"10"
,
"EN"
,
"10-EN"
);
INSERT
INTO
t2
VALUES
(
"10"
,
"SV"
,
"10-SV"
);
INSERT
INTO
t2
VALUES
(
"10"
,
"SV"
,
"10-SV"
);
SELECT
t1
.
id
,
t1
.
text_id
,
t2
.
text_data
SELECT
t1
.
id
,
t1
.
text_id
,
t2
.
text_data
FROM
t1
LEFT
JOIN
t2
FROM
t1
LEFT
JOIN
t2
ON
t1
.
text_id
=
t2
.
text_id
ON
t1
.
text_id
=
t2
.
text_id
...
@@ -713,3 +712,49 @@ INSERT INTO t1 VALUES (30), (40), (50);
...
@@ -713,3 +712,49 @@ INSERT INTO t1 VALUES (30), (40), (50);
INSERT
INTO
t2
VALUES
(
300
),
(
400
),
(
500
);
INSERT
INTO
t2
VALUES
(
300
),
(
400
),
(
500
);
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
(
c11
=
c21
AND
c21
=
30
)
WHERE
c11
=
40
;
SELECT
*
FROM
t1
LEFT
JOIN
t2
ON
(
c11
=
c21
AND
c21
=
30
)
WHERE
c11
=
40
;
DROP
TABLE
t1
,
t2
;
DROP
TABLE
t1
,
t2
;
#
# 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
;
sql/item_cmpfunc.cc
View file @
d6398c1a
...
@@ -988,6 +988,53 @@ longlong Item_func_interval::val_int()
...
@@ -988,6 +988,53 @@ longlong Item_func_interval::val_int()
}
}
/*
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
,
Item
**
ref
)
{
if
(
Item_func_opt_neg
::
fix_fields
(
thd
,
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
;
...
@@ -1040,8 +1087,9 @@ longlong Item_func_between::val_int()
...
@@ -1040,8 +1087,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
)
...
@@ -1063,7 +1111,7 @@ longlong Item_func_between::val_int()
...
@@ -1063,7 +1111,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
)
...
@@ -1084,8 +1132,8 @@ longlong Item_func_between::val_int()
...
@@ -1084,8 +1132,8 @@ longlong Item_func_between::val_int()
a_dec
=
args
[
1
]
->
val_decimal
(
&
a_buf
);
a_dec
=
args
[
1
]
->
val_decimal
(
&
a_buf
);
b_dec
=
args
[
2
]
->
val_decimal
(
&
b_buf
);
b_dec
=
args
[
2
]
->
val_decimal
(
&
b_buf
);
if
(
!
args
[
1
]
->
null_value
&&
!
args
[
2
]
->
null_value
)
if
(
!
args
[
1
]
->
null_value
&&
!
args
[
2
]
->
null_value
)
return
(
my_decimal_cmp
(
dec
,
a_dec
)
>=
0
)
&&
(
my_decimal_cmp
(
dec
,
b_dec
)
<=
0
);
return
(
longlong
)
((
my_decimal_cmp
(
dec
,
a_dec
)
>=
0
&&
my_decimal_cmp
(
dec
,
b_dec
)
<=
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
)
...
@@ -1101,7 +1149,7 @@ longlong Item_func_between::val_int()
...
@@ -1101,7 +1149,7 @@ longlong Item_func_between::val_int()
a
=
args
[
1
]
->
val_real
();
a
=
args
[
1
]
->
val_real
();
b
=
args
[
2
]
->
val_real
();
b
=
args
[
2
]
->
val_real
();
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
)
...
@@ -1113,7 +1161,7 @@ longlong Item_func_between::val_int()
...
@@ -1113,7 +1161,7 @@ longlong Item_func_between::val_int()
null_value
=
value
>=
a
;
null_value
=
value
>=
a
;
}
}
}
}
return
0
;
return
(
longlong
)
(
!
null_value
&&
negated
)
;
}
}
...
@@ -1244,6 +1292,49 @@ Item_func_ifnull::str_op(String *str)
...
@@ -1244,6 +1292,49 @@ Item_func_ifnull::str_op(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
,
Item
**
ref
)
{
DBUG_ASSERT
(
fixed
==
0
);
args
[
0
]
->
top_level_item
();
if
(
Item_func
::
fix_fields
(
thd
,
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
()
{
{
...
@@ -2184,6 +2275,56 @@ bool Item_func_in::nulls_in_row()
...
@@ -2184,6 +2275,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
,
Item
**
ref
)
{
Item
**
arg
,
**
arg_end
;
if
(
Item_func_opt_neg
::
fix_fields
(
thd
,
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
,
...
@@ -2283,7 +2424,7 @@ longlong Item_func_in::val_int()
...
@@ -2283,7 +2424,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
))
...
@@ -2292,11 +2433,11 @@ longlong Item_func_in::val_int()
...
@@ -2292,11 +2433,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 @
d6398c1a
...
@@ -401,17 +401,49 @@ class Item_func_ne :public Item_bool_rowready_func2
...
@@ -401,17 +401,49 @@ class Item_func_ne :public Item_bool_rowready_func2
};
};
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
*
,
Item
**
);
void
fix_length_and_dec
();
void
fix_length_and_dec
();
void
print
(
String
*
str
);
void
print
(
String
*
str
);
bool
is_bool_func
()
{
return
1
;
}
bool
is_bool_func
()
{
return
1
;
}
...
@@ -505,16 +537,10 @@ class Item_func_if :public Item_func
...
@@ -505,16 +537,10 @@ class Item_func_if :public Item_func
String
*
val_str
(
String
*
str
);
String
*
val_str
(
String
*
str
);
my_decimal
*
val_decimal
(
my_decimal
*
);
my_decimal
*
val_decimal
(
my_decimal
*
);
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
,
Item
**
ref
)
bool
fix_fields
(
THD
*
,
Item
**
);
{
DBUG_ASSERT
(
fixed
==
0
);
args
[
0
]
->
top_level_item
();
return
Item_func
::
fix_fields
(
thd
,
ref
);
}
void
fix_length_and_dec
();
void
fix_length_and_dec
();
uint
decimal_precision
()
const
;
uint
decimal_precision
()
const
;
const
char
*
func_name
()
const
{
return
"if"
;
}
const
char
*
func_name
()
const
{
return
"if"
;
}
table_map
not_null_tables
()
const
{
return
0
;
}
};
};
...
@@ -819,7 +845,7 @@ class cmp_item_sort_string_in_static :public cmp_item_string
...
@@ -819,7 +845,7 @@ class cmp_item_sort_string_in_static :public cmp_item_string
}
}
};
};
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
;
...
@@ -828,11 +854,12 @@ class Item_func_in :public Item_int_func
...
@@ -828,11 +854,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
*
,
Item
**
);
void
fix_length_and_dec
();
void
fix_length_and_dec
();
uint
decimal_precision
()
const
{
return
1
;
}
uint
decimal_precision
()
const
{
return
1
;
}
void
cleanup
()
void
cleanup
()
...
@@ -853,12 +880,6 @@ class Item_func_in :public Item_int_func
...
@@ -853,12 +880,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 @
d6398c1a
...
@@ -3524,18 +3524,9 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
...
@@ -3524,18 +3524,9 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
}
}
Item_func
*
cond_func
=
(
Item_func
*
)
cond
;
Item_func
*
cond_func
=
(
Item_func
*
)
cond
;
if
(
cond_func
->
functype
()
==
Item_func
::
NOT_FUNC
)
if
(
cond_func
->
functype
()
==
Item_func
::
BETWEEN
||
{
cond_func
->
functype
()
==
Item_func
::
IN_FUNC
)
/* Optimize NOT BETWEEN and NOT IN */
inv
=
((
Item_func_opt_neg
*
)
cond_func
)
->
negated
;
Item
*
arg
=
cond_func
->
arguments
()[
0
];
if
(
arg
->
type
()
!=
Item
::
FUNC_ITEM
)
DBUG_RETURN
(
0
);
cond_func
=
(
Item_func
*
)
arg
;
if
(
cond_func
->
functype
()
!=
Item_func
::
BETWEEN
&&
cond_func
->
functype
()
!=
Item_func
::
IN_FUNC
)
DBUG_RETURN
(
0
);
inv
=
TRUE
;
}
else
if
(
cond_func
->
select_optimize
()
==
Item_func
::
OPTIMIZE_NONE
)
else
if
(
cond_func
->
select_optimize
()
==
Item_func
::
OPTIMIZE_NONE
)
DBUG_RETURN
(
0
);
DBUG_RETURN
(
0
);
...
...
sql/sql_select.cc
View file @
d6398c1a
...
@@ -2862,19 +2862,6 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
...
@@ -2862,19 +2862,6 @@ add_key_fields(KEY_FIELD **key_fields,uint *and_level,
if
(
cond
->
type
()
!=
Item
::
FUNC_ITEM
)
if
(
cond
->
type
()
!=
Item
::
FUNC_ITEM
)
return
;
return
;
Item_func
*
cond_func
=
(
Item_func
*
)
cond
;
Item_func
*
cond_func
=
(
Item_func
*
)
cond
;
if
(
cond_func
->
functype
()
==
Item_func
::
NOT_FUNC
)
{
Item
*
item
=
cond_func
->
arguments
()[
0
];
/*
At this moment all NOT before simple comparison predicates
are eliminated. NOT IN and NOT BETWEEN are treated similar
IN and BETWEEN respectively.
*/
if
(
item
->
type
()
==
Item
::
FUNC_ITEM
&&
((
Item_func
*
)
item
)
->
select_optimize
()
==
Item_func
::
OPTIMIZE_KEY
)
add_key_fields
(
key_fields
,
and_level
,
item
,
usable_tables
);
return
;
}
switch
(
cond_func
->
select_optimize
())
{
switch
(
cond_func
->
select_optimize
())
{
case
Item_func
:
:
OPTIMIZE_NONE
:
case
Item_func
:
:
OPTIMIZE_NONE
:
break
;
break
;
...
...
sql/sql_yacc.yy
View file @
d6398c1a
...
@@ -4279,7 +4279,9 @@ predicate:
...
@@ -4279,7 +4279,9 @@ predicate:
else
else
{
{
$5->push_front($1);
$5->push_front($1);
$$= negate_expression(YYTHD, new Item_func_in(*$5));
Item_func_in *item = new Item_func_in(*$5);
item->negate();
$$= item;
}
}
}
}
| bit_expr IN_SYM in_subselect
| bit_expr IN_SYM in_subselect
...
@@ -4289,7 +4291,11 @@ predicate:
...
@@ -4289,7 +4291,11 @@ predicate:
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
{ $$= new Item_func_between($1,$3,$5); }
{ $$= new Item_func_between($1,$3,$5); }
| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
{ $$= negate_expression(YYTHD, new Item_func_between($1,$4,$6)); }
{
Item_func_between *item= new Item_func_between($1,$4,$6);
item->negate();
$$= item;
}
| bit_expr SOUNDS_SYM LIKE bit_expr
| bit_expr SOUNDS_SYM LIKE bit_expr
{ $$= new Item_func_eq(new Item_func_soundex($1),
{ $$= new Item_func_eq(new Item_func_soundex($1),
new Item_func_soundex($4)); }
new Item_func_soundex($4)); }
...
...
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