summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmysqld/CMakeLists.txt1
-rw-r--r--mysql-test/r/archive_gis.result22
-rw-r--r--mysql-test/r/create.result2
-rw-r--r--mysql-test/r/ctype_binary.result6
-rw-r--r--mysql-test/r/ctype_collate.result12
-rw-r--r--mysql-test/r/ctype_cp1251.result6
-rw-r--r--mysql-test/r/ctype_latin1.result6
-rw-r--r--mysql-test/r/ctype_ucs.result6
-rw-r--r--mysql-test/r/ctype_utf8.result6
-rw-r--r--mysql-test/r/derived_view.result4
-rw-r--r--mysql-test/r/explain.result2
-rw-r--r--mysql-test/r/func_compress.result1
-rw-r--r--mysql-test/r/func_in.result52
-rw-r--r--mysql-test/r/func_str.result1
-rw-r--r--mysql-test/r/gis-precise.result436
-rw-r--r--mysql-test/r/gis-rt-precise.result49
-rw-r--r--mysql-test/r/gis-rtree.result466
-rw-r--r--mysql-test/r/gis.result457
-rw-r--r--mysql-test/r/group_by.result7
-rw-r--r--mysql-test/r/group_min_max.result5
-rw-r--r--mysql-test/r/index_intersect.result18
-rw-r--r--mysql-test/r/index_merge_innodb.result2
-rw-r--r--mysql-test/r/index_merge_myisam.result6
-rw-r--r--mysql-test/r/join.result2
-rw-r--r--mysql-test/r/join_nested.result4
-rw-r--r--mysql-test/r/join_optimizer.result2
-rw-r--r--mysql-test/r/key_cache.result2
-rw-r--r--mysql-test/r/merge.result2
-rw-r--r--mysql-test/r/mix2_myisam.result4
-rw-r--r--mysql-test/r/myisam.result2
-rw-r--r--mysql-test/r/myisam_icp.result4
-rw-r--r--mysql-test/r/mysqld--help-notwin.result2
-rw-r--r--mysql-test/r/mysqld--help-win.result208
-rw-r--r--mysql-test/r/null.result4
-rw-r--r--mysql-test/r/null_key.result22
-rw-r--r--mysql-test/r/order_by.result22
-rw-r--r--mysql-test/r/ps.result61
-rw-r--r--mysql-test/r/ps_1general.result4
-rw-r--r--mysql-test/r/range.result70
-rw-r--r--mysql-test/r/range_vs_index_merge.result122
-rw-r--r--mysql-test/r/range_vs_index_merge_innodb.result128
-rw-r--r--mysql-test/r/select.result28
-rw-r--r--mysql-test/r/select_pkeycache.result28
-rw-r--r--mysql-test/r/subselect.result42
-rw-r--r--mysql-test/r/subselect3.result29
-rw-r--r--mysql-test/r/subselect3_jcl6.result27
-rw-r--r--mysql-test/r/subselect4.result9
-rw-r--r--mysql-test/r/subselect_cache.result8
-rw-r--r--mysql-test/r/subselect_extra.result3
-rw-r--r--mysql-test/r/subselect_extra_no_semijoin.result12
-rw-r--r--mysql-test/r/subselect_mat.result2
-rw-r--r--mysql-test/r/subselect_mat_cost_bugs.result7
-rw-r--r--mysql-test/r/subselect_no_mat.result14
-rw-r--r--mysql-test/r/subselect_no_opts.result10
-rw-r--r--mysql-test/r/subselect_no_scache.result42
-rw-r--r--mysql-test/r/subselect_no_semijoin.result98
-rw-r--r--mysql-test/r/subselect_sj.result83
-rw-r--r--mysql-test/r/subselect_sj2.result53
-rw-r--r--mysql-test/r/subselect_sj2_jcl6.result57
-rw-r--r--mysql-test/r/subselect_sj2_mat.result2
-rw-r--r--mysql-test/r/subselect_sj_jcl6.result131
-rw-r--r--mysql-test/r/table_elim.result8
-rw-r--r--mysql-test/suite/innodb/r/innodb_gis.result22
-rw-r--r--mysql-test/suite/innodb/r/innodb_mysql.result2
-rw-r--r--mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test2
-rw-r--r--mysql-test/suite/innodb/t/innodb_mysql.test2
-rw-r--r--mysql-test/suite/maria/r/maria-gis-rtree-dynamic.result8
-rw-r--r--mysql-test/suite/maria/r/maria-gis-rtree-trans.result8
-rw-r--r--mysql-test/suite/maria/r/maria-gis-rtree.result8
-rw-r--r--mysql-test/suite/maria/r/maria.result4
-rw-r--r--mysql-test/suite/pbxt/r/group_by.result6
-rw-r--r--mysql-test/suite/pbxt/r/group_min_max.result5
-rw-r--r--mysql-test/suite/pbxt/r/null_key.result22
-rw-r--r--mysql-test/suite/pbxt/r/order_by.result2
-rw-r--r--mysql-test/suite/pbxt/r/ps_1general.result4
-rw-r--r--mysql-test/suite/pbxt/r/range.result4
-rw-r--r--mysql-test/suite/pbxt/r/subselect.result13
-rw-r--r--mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result22
-rw-r--r--mysql-test/suite/sys_vars/r/optimizer_switch_basic.result16
-rw-r--r--mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown1.result2
-rw-r--r--mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown2.result2
-rw-r--r--mysql-test/suite/vcol/r/vcol_select_innodb.result20
-rw-r--r--mysql-test/suite/vcol/r/vcol_select_myisam.result18
-rw-r--r--mysql-test/t/derived_view.test4
-rw-r--r--mysql-test/t/gis-precise.test312
-rw-r--r--mysql-test/t/gis-rt-precise.test64
-rw-r--r--mysql-test/t/gis-rtree.test12
-rw-r--r--mysql-test/t/gis.test562
-rw-r--r--mysql-test/t/ps.test28
-rwxr-xr-xmysql-test/t/range_vs_index_merge.test36
-rw-r--r--mysql-test/t/subselect.test10
-rw-r--r--mysql-test/t/subselect3.test25
-rw-r--r--mysql-test/t/subselect4.test5
-rw-r--r--mysql-test/t/subselect_mat_cost_bugs.test4
-rw-r--r--mysql-test/t/subselect_sj.test30
-rw-r--r--mysql-test/t/subselect_sj_jcl6.test42
-rw-r--r--sql/CMakeLists.txt1
-rw-r--r--sql/field.cc2
-rw-r--r--sql/gcalc_slicescan.cc1966
-rw-r--r--sql/gcalc_slicescan.h595
-rw-r--r--sql/gcalc_tools.cc1429
-rw-r--r--sql/gcalc_tools.h348
-rw-r--r--sql/gstream.cc23
-rw-r--r--sql/gstream.h9
-rw-r--r--sql/item_create.cc355
-rw-r--r--sql/item_geofunc.cc1092
-rw-r--r--sql/item_geofunc.h225
-rw-r--r--sql/opt_range.cc6
-rw-r--r--sql/opt_subselect.cc6
-rw-r--r--sql/opt_subselect.h2
-rw-r--r--sql/plistsort.c166
-rw-r--r--sql/spatial.cc738
-rw-r--r--sql/spatial.h50
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_priv.h7
-rw-r--r--sql/sql_select.cc12
-rw-r--r--storage/xtradb/handler/ha_innodb.cc8
-rw-r--r--storage/xtradb/include/srv0srv.h6
-rw-r--r--storage/xtradb/srv/srv0srv.c6
119 files changed, 10421 insertions, 890 deletions
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 483e0ca05fd..3ced8de401d 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -76,6 +76,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_tablespace.cc ../sql/sql_table.cc ../sql/sql_test.cc
../sql/sql_trigger.cc ../sql/sql_udf.cc ../sql/sql_union.cc
../sql/sql_update.cc ../sql/sql_view.cc ../sql/sql_profile.cc
+ ../sql/gcalc_tools.cc ../sql/gcalc_slicescan.cc
../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
../sql/sql_time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
../sql/partition_info.cc ../sql/sql_connect.cc
diff --git a/mysql-test/r/archive_gis.result b/mysql-test/r/archive_gis.result
index bcdf9ec4381..97f48407db2 100644
--- a/mysql-test/r/archive_gis.result
+++ b/mysql-test/r/archive_gis.result
@@ -236,7 +236,7 @@ explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelo
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 100.00
Warnings:
-Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry`
+Note 1003 select st_dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,st_geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,st_isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,st_astext(st_envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry`
SELECT fid, X(g) FROM gis_point ORDER by fid;
fid X(g)
101 10
@@ -253,7 +253,7 @@ explain extended select X(g),Y(g) FROM gis_point;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 100.00
Warnings:
-Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point`
+Note 1003 select st_x(`test`.`gis_point`.`g`) AS `X(g)`,st_y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point`
SELECT fid, AsText(StartPoint(g)) FROM gis_line ORDER by fid;
fid AsText(StartPoint(g))
105 POINT(0 0)
@@ -288,7 +288,7 @@ explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),Num
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line`
+Note 1003 select st_astext(st_startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,st_astext(st_endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,st_length(`test`.`gis_line`.`g`) AS `GLength(g)`,st_numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,st_astext(st_pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,st_isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line`
SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid;
fid AsText(Centroid(g))
108 POINT(15 15)
@@ -318,7 +318,7 @@ explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumI
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon`
+Note 1003 select st_astext(st_centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,st_area(`test`.`gis_polygon`.`g`) AS `Area(g)`,st_astext(st_exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,st_numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,st_astext(st_interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon`
SELECT fid, IsClosed(g) FROM gis_multi_line ORDER by fid;
fid IsClosed(g)
114 0
@@ -357,7 +357,7 @@ explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point`
+Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,st_numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point`
SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point ORDER by fid;
fid AsText(GeometryN(g, 2))
111 POINT(10 10)
@@ -385,17 +385,17 @@ explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point`
+Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,st_astext(st_geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point`
SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
first second w c o e d t i r
-120 120 1 1 0 1 0 0 1 0
+120 120 1 1 0 1 0 1 1 0
120 121 0 0 1 0 0 0 1 0
121 120 0 0 1 0 0 0 1 0
-121 121 1 1 0 1 0 0 1 0
+121 121 1 1 0 1 0 1 1 0
explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
@@ -405,7 +405,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE g1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
1 SIMPLE g2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid`
+Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,st_within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,st_contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,mbroverlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,st_equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,mbrdisjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,st_touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,mbrintersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,st_crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid`
DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
CREATE TABLE t1 (
a INTEGER PRIMARY KEY AUTO_INCREMENT,
@@ -494,7 +494,7 @@ mbroverlaps
down,left,right,up
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrtouches FROM t1 a1 JOIN t1 a2 ON MBRTouches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
mbrtouches
-down2,left2,right2,up2
+big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1 a2 ON MBRWithin( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
mbrwithin
big,center
@@ -515,7 +515,7 @@ overlaps
down,left,right,up
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS touches FROM t1 a1 JOIN t1 a2 ON Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
touches
-down2,left2,right2,up2
+big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS within FROM t1 a1 JOIN t1 a2 ON Within( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
within
big,center
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 5bd323ce8d1..c07e313b3f6 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -113,7 +113,7 @@ insert into t1 (b) values ("hello"),("my"),("world");
create table t2 (key (b)) select * from t1;
explain select * from t2 where b="world";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref B B 21 const 1 Using where
+1 SIMPLE t2 ref B B 21 const 1 Using index condition
select * from t2 where b="world";
a B
3 world
diff --git a/mysql-test/r/ctype_binary.result b/mysql-test/r/ctype_binary.result
index 2cf59806571..b8ef2a50733 100644
--- a/mysql-test/r/ctype_binary.result
+++ b/mysql-test/r/ctype_binary.result
@@ -1184,7 +1184,7 @@ t1 CREATE TABLE `t1` (
drop table t1;
select hex(concat(IsSimple(GeomFromText('POINT(1 1)'))));
hex(concat(IsSimple(GeomFromText('POINT(1 1)'))))
-30
+31
create table t1 as select concat(IsSimple(GeomFromText('Point(1 1)'))) as c1;
show create table t1;
Table Create Table
@@ -2761,11 +2761,11 @@ KEY(date_column));
INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01');
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 4 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 4 NULL 1 Using index condition
ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL;
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 9 NULL 1 Using index condition
DROP TABLE t1;
#
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
diff --git a/mysql-test/r/ctype_collate.result b/mysql-test/r/ctype_collate.result
index 67262a4935d..453119f0412 100644
--- a/mysql-test/r/ctype_collate.result
+++ b/mysql-test/r/ctype_collate.result
@@ -596,31 +596,31 @@ INSERT INTO t1 VALUES ('i','i');
INSERT INTO t1 VALUES ('j','j');
EXPLAIN SELECT * FROM t1 WHERE s1='a';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref s1 s1 11 const 1 Using where
+1 SIMPLE t1 ref s1 s1 11 const 1 Using index condition
EXPLAIN SELECT * FROM t1 WHERE s2='a';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref s2 s2 11 const 1 Using where
+1 SIMPLE t1 ref s2 s2 11 const 1 Using index condition
EXPLAIN SELECT * FROM t1 WHERE s1='a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref s1 s1 11 const 1 Using where
+1 SIMPLE t1 ref s1 s1 11 const 1 Using index condition
EXPLAIN SELECT * FROM t1 WHERE s2='a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
EXPLAIN SELECT * FROM t1 WHERE s1 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range s1 s1 11 NULL 2 Using where
+1 SIMPLE t1 range s1 s1 11 NULL 2 Using index condition
EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
EXPLAIN SELECT * FROM t1 WHERE s1 IN ('a','b' COLLATE latin1_german1_ci);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range s1 s1 11 NULL 2 Using where
+1 SIMPLE t1 range s1 s1 11 NULL 2 Using index condition
EXPLAIN SELECT * FROM t1 WHERE s2 IN ('a','b' COLLATE latin1_german1_ci);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range s1 s1 11 NULL 1 Using where
+1 SIMPLE t1 range s1 s1 11 NULL 1 Using index condition
EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where
diff --git a/mysql-test/r/ctype_cp1251.result b/mysql-test/r/ctype_cp1251.result
index f3b36e89863..cb700f2feb8 100644
--- a/mysql-test/r/ctype_cp1251.result
+++ b/mysql-test/r/ctype_cp1251.result
@@ -1576,7 +1576,7 @@ t1 CREATE TABLE `t1` (
drop table t1;
select hex(concat(IsSimple(GeomFromText('POINT(1 1)'))));
hex(concat(IsSimple(GeomFromText('POINT(1 1)'))))
-30
+31
create table t1 as select concat(IsSimple(GeomFromText('Point(1 1)'))) as c1;
show create table t1;
Table Create Table
@@ -3153,11 +3153,11 @@ KEY(date_column));
INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01');
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 4 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 4 NULL 1 Using index condition
ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL;
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 9 NULL 1 Using index condition
DROP TABLE t1;
#
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result
index 61b19b479aa..3f51716bc34 100644
--- a/mysql-test/r/ctype_latin1.result
+++ b/mysql-test/r/ctype_latin1.result
@@ -1603,7 +1603,7 @@ t1 CREATE TABLE `t1` (
drop table t1;
select hex(concat(IsSimple(GeomFromText('POINT(1 1)'))));
hex(concat(IsSimple(GeomFromText('POINT(1 1)'))))
-30
+31
create table t1 as select concat(IsSimple(GeomFromText('Point(1 1)'))) as c1;
show create table t1;
Table Create Table
@@ -3180,11 +3180,11 @@ KEY(date_column));
INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01');
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 4 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 4 NULL 1 Using index condition
ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL;
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 9 NULL 1 Using index condition
DROP TABLE t1;
#
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 892bcaee574..c8f031f8ca7 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -2486,7 +2486,7 @@ t1 CREATE TABLE `t1` (
drop table t1;
select hex(concat(IsSimple(GeomFromText('POINT(1 1)'))));
hex(concat(IsSimple(GeomFromText('POINT(1 1)'))))
-0030
+0031
create table t1 as select concat(IsSimple(GeomFromText('Point(1 1)'))) as c1;
show create table t1;
Table Create Table
@@ -4063,11 +4063,11 @@ KEY(date_column));
INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01');
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 4 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 4 NULL 1 Using index condition
ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL;
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 9 NULL 1 Using index condition
DROP TABLE t1;
#
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 5cc957fea9c..0ada8bae8c2 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -3318,7 +3318,7 @@ t1 CREATE TABLE `t1` (
drop table t1;
select hex(concat(IsSimple(GeomFromText('POINT(1 1)'))));
hex(concat(IsSimple(GeomFromText('POINT(1 1)'))))
-30
+31
create table t1 as select concat(IsSimple(GeomFromText('Point(1 1)'))) as c1;
show create table t1;
Table Create Table
@@ -4895,11 +4895,11 @@ KEY(date_column));
INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01');
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 4 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 4 NULL 1 Using index condition
ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL;
EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where
+1 SIMPLE t1 range date_column date_column 9 NULL 1 Using index condition
DROP TABLE t1;
#
# Bug #31384 DATE_ADD() and DATE_SUB() return binary data
diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result
index 30c4d330e64..591aaded9f1 100644
--- a/mysql-test/r/derived_view.result
+++ b/mysql-test/r/derived_view.result
@@ -778,7 +778,7 @@ DROP TABLE t1;
#
# LP bug #803851: materialized view + IN->EXISTS
#
-SET SESSION optimizer_switch='semijoin=off,derived_with_keys=on';
+SET SESSION optimizer_switch='semijoin=off,derived_with_keys=on,materialization=off';
CREATE TABLE t1 (a int, b int);
INSERT INTO t1 VALUES (2,2), (3,3), (1,1);
CREATE TABLE t2 (a int);
@@ -1448,7 +1448,7 @@ KEY (c,a) , PRIMARY KEY (a)
INSERT INTO t3 VALUES
(14,4,'a'), (15,7,'b'), (16,4,'c'), (17,1,'d'), (18,9,'e'),
(19,4,'f'), (20,8,'g');
-SET SESSION optimizer_switch='derived_merge=on,subquery_cache=off';
+SET SESSION optimizer_switch='derived_merge=on,subquery_cache=off,materialization=off';
# The following two EXPLAINs must return the same execution plan
EXPLAIN
SELECT * FROM t1 , t2
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index 65bc5b22ba8..36aefafa8e2 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -13,7 +13,7 @@ id str
3 foo
explain select * from t1 where str is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref str str 11 const 1 Using where
+1 SIMPLE t1 ref str str 11 const 1 Using index condition
explain select * from t1 where str="foo";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const str str 11 const 1
diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result
index 9a221a264a0..02284186c76 100644
--- a/mysql-test/r/func_compress.result
+++ b/mysql-test/r/func_compress.result
@@ -103,7 +103,6 @@ foo
Warnings:
Warning 1259 ZLIB: Input data corrupted
Warning 1259 ZLIB: Input data corrupted
-Warning 1259 ZLIB: Input data corrupted
explain select *, uncompress(a) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index 779049f8b4c..650f103710d 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -241,7 +241,7 @@ insert into t2 select C.a*2+1, 'yes' from t1 C;
explain
select * from t2 where a NOT IN (0, 2,4,6,8,10,12,14,16,18);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 5 NULL 12 Using where
+1 SIMPLE t2 range a a 5 NULL 12 Using index condition
select * from t2 where a NOT IN (0, 2,4,6,8,10,12,14,16,18);
a filler
1 yes
@@ -256,10 +256,10 @@ a filler
19 yes
explain select * from t2 force index(a) where a NOT IN (2,2,2,2,2,2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 5 NULL 912 Using where
+1 SIMPLE t2 range a a 5 NULL 912 Using index condition
explain select * from t2 force index(a) where a <> 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 5 NULL 912 Using where
+1 SIMPLE t2 range a a 5 NULL 912 Using index condition
drop table t2;
create table t2 (a datetime, filler char(200), key(a));
insert into t2 select '2006-04-25 10:00:00' + interval C.a minute,
@@ -271,7 +271,7 @@ select * from t2 where a NOT IN (
'2006-04-25 10:00:00','2006-04-25 10:02:00','2006-04-25 10:04:00',
'2006-04-25 10:06:00', '2006-04-25 10:08:00');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 9 NULL 18 Using where
+1 SIMPLE t2 range a a 9 NULL 18 Using index condition
select * from t2 where a NOT IN (
'2006-04-25 10:00:00','2006-04-25 10:02:00','2006-04-25 10:04:00',
'2006-04-25 10:06:00', '2006-04-25 10:08:00');
@@ -295,7 +295,7 @@ insert into t2 values ('fon', '1'), ('fop','1'), ('barbaq','1'),
('barbas','1'), ('bazbazbay', '1'),('zz','1');
explain select * from t2 where a not in('foo','barbar', 'bazbazbaz');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 13 NULL 7 Using where
+1 SIMPLE t2 range a a 13 NULL 7 Using index condition
drop table t2;
create table t2 (a decimal(10,5), filler char(200), key(a));
insert into t2 select 345.67890, 'no' from t1 A, t1 B;
@@ -306,7 +306,7 @@ insert into t2 values (0, '1'), (22334.123,'1'), (33333,'1'),
explain
select * from t2 where a not in (345.67890, 43245.34, 64224.56344);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 7 NULL 7 Using where
+1 SIMPLE t2 range a a 7 NULL 7 Using index condition
select * from t2 where a not in (345.67890, 43245.34, 64224.56344);
a filler
0.00000 1
@@ -630,16 +630,16 @@ INSERT INTO t1 (c_int) SELECT 0 FROM t1;
INSERT INTO t1 (c_int) SELECT 0 FROM t1;
EXPLAIN SELECT * FROM t1 WHERE c_int IN (1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_int c_int 4 NULL 3 Using where
+1 SIMPLE t1 range c_int c_int 4 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_int IN (NULL, 1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_int c_int 4 NULL 3 Using where
+1 SIMPLE t1 range c_int c_int 4 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_int IN (1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_int c_int 4 NULL 3 Using where
+1 SIMPLE t1 range c_int c_int 4 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_int IN (1, NULL, 2, NULL, 3, NULL);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_int c_int 4 NULL 3 Using where
+1 SIMPLE t1 range c_int c_int 4 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_int IN (NULL);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@@ -648,10 +648,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE c_decimal IN (1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_decimal c_decimal 3 NULL 3 Using where
+1 SIMPLE t1 range c_decimal c_decimal 3 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_decimal IN (NULL, 1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_decimal c_decimal 3 NULL 3 Using where
+1 SIMPLE t1 range c_decimal c_decimal 3 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_decimal IN (NULL);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@@ -660,10 +660,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE c_float IN (1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_float c_float 4 NULL 3 Using where
+1 SIMPLE t1 range c_float c_float 4 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_float IN (NULL, 1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_float c_float 4 NULL 3 Using where
+1 SIMPLE t1 range c_float c_float 4 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_float IN (NULL);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@@ -672,10 +672,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE c_bit IN (1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_bit c_bit 2 NULL 3 Using where
+1 SIMPLE t1 range c_bit c_bit 2 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_bit IN (NULL, 1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_bit c_bit 2 NULL 3 Using where
+1 SIMPLE t1 range c_bit c_bit 2 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_bit IN (NULL);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@@ -685,11 +685,11 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT * FROM t1 WHERE c_date
IN ('2009-09-01', '2009-09-02', '2009-09-03');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_date c_date 3 NULL 3 Using where
+1 SIMPLE t1 range c_date c_date 3 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_date
IN (NULL, '2009-09-01', '2009-09-02', '2009-09-03');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_date c_date 3 NULL 3 Using where
+1 SIMPLE t1 range c_date c_date 3 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_date IN (NULL);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@@ -699,11 +699,11 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT * FROM t1 WHERE c_datetime
IN ('2009-09-01 00:00:01', '2009-09-02 00:00:01', '2009-09-03 00:00:01');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_datetime c_datetime 8 NULL 3 Using where
+1 SIMPLE t1 range c_datetime c_datetime 8 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_datetime
IN (NULL, '2009-09-01 00:00:01', '2009-09-02 00:00:01', '2009-09-03 00:00:01');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_datetime c_datetime 8 NULL 3 Using where
+1 SIMPLE t1 range c_datetime c_datetime 8 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_datetime IN (NULL);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@@ -713,11 +713,11 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT * FROM t1 WHERE c_timestamp
IN ('2009-09-01 00:00:01', '2009-09-01 00:00:02', '2009-09-01 00:00:03');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_timestamp c_timestamp 4 NULL 3 Using where
+1 SIMPLE t1 range c_timestamp c_timestamp 4 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_timestamp
IN (NULL, '2009-09-01 00:00:01', '2009-09-01 00:00:02', '2009-09-01 00:00:03');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_timestamp c_timestamp 4 NULL 3 Using where
+1 SIMPLE t1 range c_timestamp c_timestamp 4 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_timestamp IN (NULL);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@@ -726,10 +726,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE c_year IN (1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_year c_year 1 NULL 3 Using where
+1 SIMPLE t1 range c_year c_year 1 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_year IN (NULL, 1, 2, 3);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_year c_year 1 NULL 3 Using where
+1 SIMPLE t1 range c_year c_year 1 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_year IN (NULL);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@@ -738,10 +738,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
EXPLAIN SELECT * FROM t1 WHERE c_char IN ('1', '2', '3');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_char c_char 10 NULL 3 Using where
+1 SIMPLE t1 range c_char c_char 10 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_char IN (NULL, '1', '2', '3');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c_char c_char 10 NULL 3 Using where
+1 SIMPLE t1 range c_char c_char 10 NULL 3 Using index condition
EXPLAIN SELECT * FROM t1 WHERE c_char IN (NULL);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 4d512601216..e08a0eef906 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -1154,7 +1154,6 @@ notnumber 0
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'notnumber'
Warning 1292 Truncated incorrect DOUBLE value: 'notnumber'
-Warning 1292 Truncated incorrect DOUBLE value: 'notnumber'
SELECT * FROM t1, t2 WHERE num=substring(str from 1 for 6);
str num
notnumber 0
diff --git a/mysql-test/r/gis-precise.result b/mysql-test/r/gis-precise.result
new file mode 100644
index 00000000000..1cd72d0c178
--- /dev/null
+++ b/mysql-test/r/gis-precise.result
@@ -0,0 +1,436 @@
+DROP TABLE IF EXISTS t1;
+select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 0,20 20,0 20,0 0))'), GeomFromText('POLYGON((10 10,30 10,30 30,10 30,10 10))'));
+1 ST_Intersects(GeomFromText('POLYGON((0 0,20 0,20 20,0 20,0 0))'), GeomFromText('POLYGON((10 10,30 10,30 30,10 30,10 10))'))
+1 1
+select 0, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 40, 40 50, 20 70, 10 40))'));
+0 ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 40, 40 50, 20 70, 10 40))'))
+0 0
+select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POINT(10 10)'));
+1 ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POINT(10 10)'))
+1 1
+select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
+1 ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'))
+1 1
+select 0, ST_Within(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
+0 ST_Within(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'))
+0 0
+select 1, ST_Within(GeomFromText('POLYGON((1 1,20 10,10 30, 1 1))'), GeomFromText('POLYGON((0 0,30 5,10 40, 0 0))'));
+1 ST_Within(GeomFromText('POLYGON((1 1,20 10,10 30, 1 1))'), GeomFromText('POLYGON((0 0,30 5,10 40, 0 0))'))
+1 1
+create table t1 (g point);
+insert into t1 values
+(GeomFromText('POINT(2 2)')), (GeomFromText('POINT(2 4)')), (GeomFromText('POINT(2 6)')), (GeomFromText('POINT(2 8)')),
+(GeomFromText('POINT(4 2)')), (GeomFromText('POINT(4 4)')), (GeomFromText('POINT(4 6)')), (GeomFromText('POINT(4 8)')),
+(GeomFromText('POINT(6 2)')), (GeomFromText('POINT(6 4)')), (GeomFromText('POINT(6 6)')), (GeomFromText('POINT(6 8)')),
+(GeomFromText('POINT(8 2)')), (GeomFromText('POINT(8 4)')), (GeomFromText('POINT(8 6)')), (GeomFromText('POINT(8 8)'));
+select astext(g) from t1 where ST_Within(g, GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'));
+astext(g)
+POINT(4 4)
+POINT(6 2)
+POINT(6 4)
+POINT(6 6)
+select 'Contains';
+Contains
+Contains
+select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g);
+astext(g)
+POINT(4 4)
+POINT(6 2)
+POINT(6 4)
+POINT(6 6)
+select 'Intersects';
+Intersects
+Intersects
+select astext(g) from t1 where ST_Intersects(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g);
+astext(g)
+POINT(4 4)
+POINT(6 2)
+POINT(6 4)
+POINT(6 6)
+select 'Contains';
+Contains
+Contains
+select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g);
+astext(g)
+POINT(4 4)
+POINT(6 2)
+POINT(6 4)
+POINT(6 6)
+select 'Contains2';
+Contains2
+Contains2
+select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1), (5.01 3.01, 6 5, 9 5, 8 3, 5.01 3.01))'), g);
+astext(g)
+POINT(4 4)
+POINT(6 2)
+POINT(6 6)
+POINT(8 4)
+DROP TABLE t1;
+select 0, ST_Within(GeomFromText('LINESTRING(15 15, 50 50, 60 60)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
+0 ST_Within(GeomFromText('LINESTRING(15 15, 50 50, 60 60)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'))
+0 0
+select 1, ST_Within(GeomFromText('LINESTRING(15 15, 16 16)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
+1 ST_Within(GeomFromText('LINESTRING(15 15, 16 16)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'))
+1 1
+select 1, ST_Intersects(GeomFromText('LINESTRING(15 15, 50 50)'), GeomFromText('LINESTRING(50 15, 15 50)'));
+1 ST_Intersects(GeomFromText('LINESTRING(15 15, 50 50)'), GeomFromText('LINESTRING(50 15, 15 50)'))
+1 1
+select 0, ST_Intersects(GeomFromText('LINESTRING(15 15, 50 50)'), GeomFromText('LINESTRING(16 16, 51 51)'));
+0 ST_Intersects(GeomFromText('LINESTRING(15 15, 50 50)'), GeomFromText('LINESTRING(16 16, 51 51)'))
+0 1
+select 1, ST_Intersects(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POLYGON((50 5, 55 10, 0 45, 50 5))'));
+1 ST_Intersects(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POLYGON((50 5, 55 10, 0 45, 50 5))'))
+1 1
+select astext(ST_Union(geometryfromtext('point(1 1)'), geometryfromtext('polygon((0 0, 2 0, 1 2, 0 0))')));
+astext(ST_Union(geometryfromtext('point(1 1)'), geometryfromtext('polygon((0 0, 2 0, 1 2, 0 0))')))
+POLYGON((0 0,1 2,2 0,0 0))
+select astext(ST_Intersection(geometryfromtext('point(1 1)'), geometryfromtext('polygon((0 0, 2 0, 1 2, 0 0))')));
+astext(ST_Intersection(geometryfromtext('point(1 1)'), geometryfromtext('polygon((0 0, 2 0, 1 2, 0 0))')))
+POINT(1 1)
+select ST_Intersects(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POLYGON((50 5, 55 10, 0 45, 50 5))'));
+ST_Intersects(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POLYGON((50 5, 55 10, 0 45, 50 5))'))
+1
+select ST_contains(GeomFromText('MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)), ((6 6, 6 11, 11 11, 11 6, 6 6)))'), GeomFromText('POINT(5 10)'));
+ST_contains(GeomFromText('MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)), ((6 6, 6 11, 11 11, 11 6, 6 6)))'), GeomFromText('POINT(5 10)'))
+0
+select ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 15, 15 15, 15 10, 10 10))'));
+ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 15, 15 15, 15 10, 10 10))'))
+1
+select ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 4, 4 4, 4 10, 10 10))'));
+ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 4, 4 4, 4 10, 10 10))'))
+0
+select ST_Overlaps(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 4, 4 4, 4 10, 10 10))'));
+ST_Overlaps(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 4, 4 4, 4 10, 10 10))'))
+1
+select ST_Overlaps(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((1 1, 1 4, 4 4, 4 1, 1 1))'));
+ST_Overlaps(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((1 1, 1 4, 4 4, 4 1, 1 1))'))
+0
+select ST_DISTANCE(geomfromtext('polygon((0 0, 1 2, 2 1, 0 0))'), geomfromtext('polygon((2 2, 3 4, 4 3, 2 2))'));
+ST_DISTANCE(geomfromtext('polygon((0 0, 1 2, 2 1, 0 0))'), geomfromtext('polygon((2 2, 3 4, 4 3, 2 2))'))
+0.7071067811865475
+select ST_DISTANCE(geomfromtext('polygon((0 0, 1 2, 2 1, 0 0))'), geomfromtext('linestring(0 1, 1 0)'));
+ST_DISTANCE(geomfromtext('polygon((0 0, 1 2, 2 1, 0 0))'), geomfromtext('linestring(0 1, 1 0)'))
+0
+select ST_DISTANCE(geomfromtext('polygon((0 0, 3 6, 6 3, 0 0))'), geomfromtext('polygon((2 2, 3 4, 4 3, 2 2))'));
+ST_DISTANCE(geomfromtext('polygon((0 0, 3 6, 6 3, 0 0))'), geomfromtext('polygon((2 2, 3 4, 4 3, 2 2))'))
+0
+select ST_DISTANCE(geomfromtext('polygon((0 0, 3 6, 6 3, 0 0),(2 2, 3 4, 4 3, 2 2))'), geomfromtext('point(3 3)'));
+ST_DISTANCE(geomfromtext('polygon((0 0, 3 6, 6 3, 0 0),(2 2, 3 4, 4 3, 2 2))'), geomfromtext('point(3 3)'))
+0.4472135954999579
+select ST_DISTANCE(geomfromtext('linestring(0 0, 3 6, 6 3, 0 0)'), geomfromtext('polygon((2 2, 3 4, 4 3, 2 2))'));
+ST_DISTANCE(geomfromtext('linestring(0 0, 3 6, 6 3, 0 0)'), geomfromtext('polygon((2 2, 3 4, 4 3, 2 2))'))
+0.8944271909999159
+select astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POLYGON((50 5, 55 10, 0 45, 50 5))')));
+astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POLYGON((50 5, 55 10, 0 45, 50 5))')))
+POLYGON((26.47058823529412 23.823529411764707,21.951219512195124 27.439024390243905,23.855421686746986 29.819277108433734,29.289940828402365 26.36094674556213,26.47058823529412 23.823529411764707))
+select astext(ST_Intersection(GeomFromText('LINESTRING(0 0, 50 45, 40 50, 0 0)'), GeomFromText('LINESTRING(50 5, 55 10, 0 45, 50 5)')));
+astext(ST_Intersection(GeomFromText('LINESTRING(0 0, 50 45, 40 50, 0 0)'), GeomFromText('LINESTRING(50 5, 55 10, 0 45, 50 5)')))
+MULTIPOINT(26.47058823529412 23.823529411764707,29.289940828402365 26.36094674556213,21.951219512195124 27.439024390243905,23.855421686746986 29.819277108433734)
+select astext(ST_Intersection(GeomFromText('LINESTRING(0 0, 50 45, 40 50)'), GeomFromText('LINESTRING(50 5, 55 10, 0 45)')));
+astext(ST_Intersection(GeomFromText('LINESTRING(0 0, 50 45, 40 50)'), GeomFromText('LINESTRING(50 5, 55 10, 0 45)')))
+POINT(29.289940828402365 26.36094674556213)
+select astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POINT(20 20)')));
+astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POINT(20 20)')))
+POINT(20 20)
+select astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200)')));
+astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200)')))
+LINESTRING(0 0,46.666666666666664 46.666666666666664)
+select astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200, 199 201, -11 -9)')));
+astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200, 199 201, -11 -9)')))
+MULTILINESTRING((0 0,46.666666666666664 46.666666666666664),(8 10,45.33333333333333 47.33333333333333))
+select astext(ST_UNION(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200, 199 201, -11 -9)')));
+astext(ST_UNION(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200, 199 201, -11 -9)')))
+GEOMETRYCOLLECTION(LINESTRING(-10 -10,0 0),LINESTRING(-11 -9,8 10),POLYGON((0 0,40 50,50 45,0 0)),LINESTRING(46.666666666666664 46.666666666666664,200 200,199 201,45.33333333333333 47.33333333333333))
+select astext(ST_intersection(geomfromtext('polygon((0 0, 1 0, 0 1, 0 0))'), geomfromtext('polygon((0 0, 1 1, 0 2, 0 0))')));
+astext(ST_intersection(geomfromtext('polygon((0 0, 1 0, 0 1, 0 0))'), geomfromtext('polygon((0 0, 1 1, 0 2, 0 0))')))
+POLYGON((0 0,0 1,0.5 0.5,0 0))
+select astext(ST_symdifference(geomfromtext('polygon((0 0, 1 0, 0 1, 0 0))'), geomfromtext('polygon((0 0, 1 1, 0 2, 0 0))')));
+astext(ST_symdifference(geomfromtext('polygon((0 0, 1 0, 0 1, 0 0))'), geomfromtext('polygon((0 0, 1 1, 0 2, 0 0))')))
+MULTIPOLYGON(((0 0,0.5 0.5,1 0,0 0)),((0.5 0.5,0 1,0 2,1 1,0.5 0.5)))
+select astext(ST_UNION(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200, 199 201, -11 -9)')));
+astext(ST_UNION(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200, 199 201, -11 -9)')))
+GEOMETRYCOLLECTION(LINESTRING(-10 -10,0 0),LINESTRING(-11 -9,8 10),POLYGON((0 0,40 50,50 45,0 0)),LINESTRING(46.666666666666664 46.666666666666664,200 200,199 201,45.33333333333333 47.33333333333333))
+select astext(ST_buffer(geometryfromtext('point(1 1)'), 1));
+astext(ST_buffer(geometryfromtext('point(1 1)'), 1))
+POLYGON((1 0,0.950932325672582 0.001204543794827595,0.9019828596704393 0.004815273327803182,0.8532695255446382 0.010823490035218986,0.8049096779838717 0.01921471959676957,0.7570198200967361 0.029968746805456026,0.7097153227455377 0.043059664267791065,0.6631101466077799 0.058455934816979194,0.6173165676349102 0.07612046748871326,0.5724449065697179 0.09601070687655666,0.5286032631740024 0.11807873565164506,0.48589725580677834 0.14227138999972788,0.4444297669803978 0.16853038769745476,0.40430069550756664 0.19679246851935517,0.3656067158363545 0.226989546637263,0.32844104515298167 0.2590488746450409,0.29289321881345254 0.29289321881345254,0.2590488746450409 0.32844104515298167,0.226989546637263 0.3656067158363545,0.19679246851935517 0.40430069550756664,0.16853038769745476 0.4444297669803978,0.14227138999972788 0.48589725580677834,0.11807873565164506 0.5286032631740024,0.09601070687655666 0.5724449065697179,0.07612046748871326 0.6173165676349102,0.058455934816979194 0.6631101466077799,0.043059664267791065 0.7097153227455377,0.029968746805456026 0.7570198200967361,0.01921471959676957 0.8049096779838717,0.010823490035218986 0.8532695255446382,0.004815273327803182 0.9019828596704393,0.001204543794827595 0.950932325672582,0 1,0.004815273327803182 1.0980171403295607,0.010823490035218986 1.146730474455362,0.01921471959676957 1.1950903220161284,0.029968746805456026 1.2429801799032638,0.043059664267791065 1.2902846772544623,0.058455934816979194 1.3368898533922202,0.07612046748871326 1.3826834323650898,0.09601070687655666 1.427555093430282,0.11807873565164506 1.4713967368259975,0.14227138999972788 1.5141027441932216,0.16853038769745476 1.5555702330196022,0.19679246851935517 1.5956993044924332,0.226989546637263 1.6343932841636455,0.2590488746450409 1.6715589548470184,0.29289321881345254 1.7071067811865475,0.32844104515298167 1.7409511253549592,0.3656067158363545 1.7730104533627369,0.40430069550756664 1.8032075314806448,0.4444297669803978 1.8314696123025453,0.48589725580677834 1.8577286100002721,0.5286032631740024 1.881921264348355,0.5724449065697179 1.9039892931234434,0.6173165676349102 1.9238795325112867,0.6631101466077799 1.9415440651830207,0.7097153227455377 1.956940335732209,0.7570198200967361 1.970031253194544,0.8049096779838717 1.9807852804032304,0.8532695255446382 1.9891765099647811,0.9019828596704393 1.9951847266721967,0.950932325672582 1.9987954562051724,1 2,1.049067674327418 1.9987954562051724,1.0980171403295607 1.9951847266721967,1.146730474455362 1.9891765099647811,1.1950903220161284 1.9807852804032304,1.2429801799032638 1.970031253194544,1.2902846772544623 1.956940335732209,1.3368898533922202 1.9415440651830207,1.3826834323650898 1.9238795325112867,1.427555093430282 1.9039892931234434,1.4713967368259975 1.881921264348355,1.5141027441932216 1.8577286100002721,1.5555702330196022 1.8314696123025453,1.5956993044924332 1.8032075314806448,1.6343932841636455 1.7730104533627369,1.6715589548470184 1.7409511253549592,1.7071067811865475 1.7071067811865475,1.7409511253549592 1.6715589548470184,1.7730104533627369 1.6343932841636455,1.8032075314806448 1.5956993044924332,1.8314696123025453 1.5555702330196022,1.8577286100002721 1.5141027441932216,1.881921264348355 1.4713967368259975,1.9039892931234434 1.427555093430282,1.9238795325112867 1.3826834323650898,1.9415440651830207 1.3368898533922202,1.956940335732209 1.2902846772544623,1.970031253194544 1.2429801799032638,1.9807852804032304 1.1950903220161284,1.9891765099647811 1.146730474455362,1.9951847266721967 1.0980171403295607,1.9987954562051724 1.049067674327418,2 1,1.9951847266721967 0.9019828596704393,1.9891765099647811 0.8532695255446382,1.9807852804032304 0.8049096779838717,1.970031253194544 0.7570198200967361,1.956940335732209 0.7097153227455377,1.9415440651830207 0.6631101466077799,1.9238795325112867 0.6173165676349102,1.9039892931234434 0.5724449065697179,1.881921264348355 0.5286032631740024,1.8577286100002721 0.48589725580677834,1.8314696123025453 0.4444297669803978,1.8032075314806448 0.40430069550756664,1.7730104533627369 0.3656067158363545,1.7409511253549592 0.32844104515298167,1.7071067811865475 0.29289321881345254,1.6715589548470184 0.2590488746450409,1.6343932841636455 0.226989546637263,1.5956993044924332 0.19679246851935517,1.5555702330196022 0.16853038769745476,1.5141027441932216 0.14227138999972788,1.4713967368259975 0.11807873565164506,1.427555093430282 0.09601070687655666,1.3826834323650898 0.07612046748871326,1.3368898533922202 0.058455934816979194,1.2902846772544623 0.043059664267791065,1.2429801799032638 0.029968746805456026,1.1950903220161284 0.01921471959676957,1.146730474455362 0.010823490035218986,1.0980171403295607 0.004815273327803182,1.049067674327418 0.001204543794827595,1 0))
+create table t1(geom geometrycollection);
+insert into t1 values (geomfromtext('POLYGON((0 0, 10 10, 0 8, 0 0))'));
+insert into t1 values (geomfromtext('POLYGON((1 1, 10 10, 0 8, 1 1))'));
+select astext(geom), area(geom),area(ST_buffer(geom,2)) from t1;
+astext(geom) area(geom) area(ST_buffer(geom,2))
+POLYGON((0 0,10 10,0 8,0 0)) 40 117.2416763959153
+POLYGON((1 1,10 10,0 8,1 1)) 36 108.55539589266459
+select astext(ST_buffer(geom,2)) from t1;
+astext(ST_buffer(geom,2))
+POLYGON((0 -2,-0.09813534865483604 -1.9975909124103448,-0.1960342806591212 -1.9903694533443936,-0.2934609489107236 -1.978353019929562,-0.3901806440322566 -1.9615705608064609,-0.4859603598065278 -1.940062506389088,-0.5805693545089246 -1.9138806714644179,-0.6737797067844402 -1.8830881303660416,-0.7653668647301796 -1.8477590650225735,-0.8551101868605642 -1.8079785862468867,-0.9427934736519952 -1.7638425286967099,-1.0282054883864433 -1.7154572200005442,-1.1111404660392044 -1.6629392246050905,-1.1913986089848667 -1.6064150629612897,-1.268786568327291 -1.546020906725474,-1.3431179096940367 -1.4819022507099182,-1.414213562373095 -1.414213562373095,-1.4819022507099182 -1.3431179096940367,-1.546020906725474 -1.268786568327291,-1.6064150629612897 -1.1913986089848667,-1.6629392246050905 -1.1111404660392044,-1.7154572200005442 -1.0282054883864433,-1.7638425286967099 -0.9427934736519952,-1.8079785862468867 -0.8551101868605642,-1.8477590650225735 -0.7653668647301796,-1.8830881303660416 -0.6737797067844402,-1.9138806714644179 -0.5805693545089246,-1.940062506389088 -0.4859603598065278,-1.9615705608064609 -0.3901806440322566,-1.978353019929562 -0.2934609489107236,-1.9903694533443936 -0.1960342806591212,-1.9975909124103448 -0.09813534865483604,-2 0,-2 8,-1.9976924709932495 8.096045777298562,-1.9905734200023315 8.193952209526529,-1.978658903288988 8.291391393893539,-1.9619776239675701 8.388128590869789,-1.940569768701071 8.483930752074583,-1.9144869108879337 8.578567081710304,-1.8837918864172196 8.67180959256969,-1.848558642291444 8.763433655277009,-1.8088720584817741 8.853218539439872,-1.7648277434447421 8.940947945408109,-1.716531803793098 9.02641052535855,-1.6641005886756872 9.109400392450459,-1.6076604094821603 9.189717616824955,-1.5473472355477698 9.267168707253568,-1.483306366591334 9.341567077275533,-1.415692082675486 9.412733494700944,-1.3446672725324915 9.480496513396783,-1.2704030411510234 9.54469288631567,-1.1930782975692584 9.605167958772302,-1.1128793238673322 9.661776041020147,-1.0299993263974934 9.714380759230782,-0.9446379703330767 9.762855384030411,-0.8570008986576141 9.807083135802014,-0.7672992367528719 9.846957466017683,-0.6757490837793165 9.882382313923348,-0.5825709920743072 9.913272337957553,-0.4879894358221987 9.939553121346753,-0.3922322702763681 9.96116135138184,9.607767729723632 11.96116135138184,9.609819355967744 11.96157056080646,9.706539051089276 11.978353019929562,9.803965719340878 11.990369453344393,9.901864651345164 11.997590912410345,10 12,10.098135348654836 11.997590912410345,10.196034280659122 11.990369453344393,10.293460948910724 11.978353019929562,10.390180644032256 11.96157056080646,10.485960359806528 11.940062506389088,10.580569354508924 11.913880671464417,10.67377970678444 11.88308813036604,10.76536686473018 11.847759065022574,10.855110186860564 11.807978586246886,10.942793473651996 11.76384252869671,11.028205488386444 11.715457220000545,11.111140466039204 11.66293922460509,11.191398608984866 11.60641506296129,11.268786568327291 11.546020906725474,11.343117909694037 11.481902250709918,11.414213562373096 11.414213562373096,11.481902250709918 11.343117909694037,11.546020906725474 11.268786568327291,11.60641506296129 11.191398608984866,11.66293922460509 11.111140466039204,11.715457220000545 11.028205488386444,11.76384252869671 10.942793473651996,11.807978586246886 10.855110186860564,11.847759065022574 10.76536686473018,11.88308813036604 10.67377970678444,11.913880671464417 10.580569354508924,11.940062506389088 10.485960359806528,11.96157056080646 10.390180644032256,11.978353019929562 10.293460948910724,11.990369453344393 10.196034280659122,11.997590912410345 10.098135348654836,12 10,11.997590912410345 9.901864651345164,11.990369453344393 9.803965719340878,11.978353019929562 9.706539051089276,11.96157056080646 9.609819355967744,11.940062506389088 9.514039640193472,11.913880671464417 9.419430645491076,11.88308813036604 9.32622029321556,11.847759065022574 9.23463313526982,11.807978586246886 9.144889813139436,11.76384252869671 9.057206526348004,11.715457220000545 8.971794511613556,11.66293922460509 8.888859533960796,11.60641506296129 8.808601391015134,11.546020906725474 8.731213431672709,11.481902250709918 8.656882090305963,11.414213562373096 8.585786437626904,1.414213562373095 -1.414213562373095,1.3431179096940367 -1.4819022507099182,1.268786568327291 -1.546020906725474,1.1913986089848667 -1.6064150629612897,1.1111404660392044 -1.6629392246050905,1.0282054883864433 -1.7154572200005442,0.9427934736519952 -1.7638425286967099,0.8551101868605642 -1.8079785862468867,0.7653668647301796 -1.8477590650225735,0.6737797067844402 -1.8830881303660416,0.5805693545089246 -1.9138806714644179,0.4859603598065278 -1.940062506389088,0.3901806440322566 -1.9615705608064609,0.2934609489107236 -1.978353019929562,0.1960342806591212 -1.9903694533443936,0.09813534865483604 -1.9975909124103448,0 -2))
+POLYGON((0.9892698494111194 -0.9999712157599518,0.8911488380683092 -0.9970356593075951,0.7932900587088283 -0.9892890690323013,0.6959292617035704 -0.9767501071485654,0.5993009977403192 -0.959448981113848,0.5036380527705995 -0.9374273708561667,0.40917088720792716 -0.9107383283634973,0.3161270807284893 -0.8794461498768888,0.2247307840117696 -0.843626220995187,0.13520217874192864 -0.8033648350645226,0.04775694717084156 -0.7587589852900836,-0.03739424747933939 -0.7099161310709878,-0.12004626852233802 -0.6569539391211774,-0.19999999999999996 -0.5999999999999999,-0.27706282637007584 -0.5391915207353741,-0.35104909653393324 -0.47467499428004234,-0.42178057108631606 -0.40660584659721555,-0.4890868517096818 -0.3351480622258147,-0.5528057916786753 -0.26047378922735365,-0.6127838864857904 -0.18276292446617926,-0.6688766436471771 -0.10220268022216916,-0.7209489307976877 -0.018987133179951154,-0.7688753012365837 0.06668324311882912,-0.8125402961396226 0.15460206123382925,-0.8518387227094812 0.2445575170314307,-0.8866759075944177 0.33633289993945015,-0.9169679249646674 0.4297071150218881,-0.9426417986971172 0.5244552156159955,-0.9636356781811806 0.6203489452484875,-0.9798989873223332 0.717157287525381,-1.9798989873223332 7.717157287525381,-1.990163308912474 7.8018838627003015,-1.9974871681520578 7.899775187364235,-1.9999989058443504 7.997907962380466,-1.9976924709932495 8.096045777298562,-1.9905734200023315 8.193952209526529,-1.978658903288988 8.291391393893539,-1.9619776239675701 8.388128590869789,-1.940569768701071 8.483930752074583,-1.9144869108879337 8.578567081710304,-1.8837918864172196 8.67180959256969,-1.848558642291444 8.763433655277009,-1.8088720584817741 8.853218539439872,-1.7648277434447421 8.940947945408109,-1.716531803793098 9.02641052535855,-1.6641005886756872 9.109400392450459,-1.6076604094821603 9.189717616824955,-1.5473472355477698 9.267168707253568,-1.483306366591334 9.341567077275533,-1.415692082675486 9.412733494700944,-1.3446672725324915 9.480496513396783,-1.2704030411510234 9.54469288631567,-1.1930782975692584 9.605167958772302,-1.1128793238673322 9.661776041020147,-1.0299993263974934 9.714380759230782,-0.9446379703330767 9.762855384030411,-0.8570008986576141 9.807083135802014,-0.7672992367528719 9.846957466017683,-0.6757490837793165 9.882382313923348,-0.5825709920743072 9.913272337957553,-0.4879894358221987 9.939553121346753,-0.3922322702763681 9.96116135138184,9.607767729723632 11.96116135138184,9.609819355967744 11.96157056080646,9.706539051089276 11.978353019929562,9.803965719340878 11.990369453344393,9.901864651345164 11.997590912410345,10 12,10.098135348654836 11.997590912410345,10.196034280659122 11.990369453344393,10.293460948910724 11.978353019929562,10.390180644032256 11.96157056080646,10.485960359806528 11.940062506389088,10.580569354508924 11.913880671464417,10.67377970678444 11.88308813036604,10.76536686473018 11.847759065022574,10.855110186860564 11.807978586246886,10.942793473651996 11.76384252869671,11.028205488386444 11.715457220000545,11.111140466039204 11.66293922460509,11.191398608984866 11.60641506296129,11.268786568327291 11.546020906725474,11.343117909694037 11.481902250709918,11.414213562373096 11.414213562373096,11.481902250709918 11.343117909694037,11.546020906725474 11.268786568327291,11.60641506296129 11.191398608984866,11.66293922460509 11.111140466039204,11.715457220000545 11.028205488386444,11.76384252869671 10.942793473651996,11.807978586246886 10.855110186860564,11.847759065022574 10.76536686473018,11.88308813036604 10.67377970678444,11.913880671464417 10.580569354508924,11.940062506389088 10.485960359806528,11.96157056080646 10.390180644032256,11.978353019929562 10.293460948910724,11.990369453344393 10.196034280659122,11.997590912410345 10.098135348654836,12 10,11.997590912410345 9.901864651345164,11.990369453344393 9.803965719340878,11.978353019929562 9.706539051089276,11.96157056080646 9.609819355967744,11.940062506389088 9.514039640193472,11.913880671464417 9.419430645491076,11.88308813036604 9.32622029321556,11.847759065022574 9.23463313526982,11.807978586246886 9.144889813139436,11.76384252869671 9.057206526348004,11.715457220000545 8.971794511613556,11.66293922460509 8.888859533960796,11.60641506296129 8.808601391015134,11.546020906725474 8.731213431672709,11.481902250709918 8.656882090305963,11.414213562373096 8.585786437626904,2.414213562373095 -0.4142135623730949,2.4066058465972153 -0.42178057108631606,2.335148062225815 -0.4890868517096818,2.260473789227354 -0.5528057916786753,2.1827629244661795 -0.6127838864857904,2.1022026802221694 -0.6688766436471771,2.018987133179951 -0.7209489307976877,1.9333167568811709 -0.7688753012365837,1.8453979387661708 -0.8125402961396226,1.7554424829685693 -0.8518387227094812,1.6636671000605499 -0.8866759075944177,1.570292884978112 -0.9169679249646674,1.4755447843840046 -0.9426417986971172,1.3796510547515126 -0.9636356781811806,1.282842712474619 -0.9798989873223332,1.1853529773292786 -0.9913925463843567,1.0874167106265484 -0.9980886663767536,0.9892698494111194 -0.9999712157599518))
+set @geom=geomfromtext('LINESTRING(2 1, 4 2, 2 3, 2 5)');
+set @buff=ST_buffer(@geom,1);
+select astext(@buff);
+astext(@buff)
+POLYGON((2.0218594008566466 0.00023894525032219782,1.9727771204112932 0.00037061126290494073,1.9237604222673113 0.002910472030148492,1.8749273919438858 0.0078524088049996,1.8263956724883341 0.015184516028905026,1.7782821810637013 0.024889130013345362,1.7307028272850733 0.03694287149320841,1.683772233983162 0.05131670194948634,1.6376034610678665 0.06797599356561079,1.592307733157046 0.08688061264889702,1.5479941716266756 0.10798501631612445,1.504769531727891 0.13123836221033125,1.46273794540424 0.1565846309845056,1.4220006704287085 0.18396276125709976,1.382655846464876 0.21330679671424568,1.3447982586398712 0.24454604500429356,1.3085191091986976 0.2776052480418776,1.2739057977900368 0.3124047633112361,1.241041710912841 0.34886075573200737,1.2100060210309511 0.38688539962528223,1.1808734958396978 0.4263870902933562,1.1537143181439746 0.46727066470347056,1.1285939167817136 0.5094376307438929,1.1055728090000843 0.5527864045000421,1.0847064546641425 0.5972125549790352,1.0660451226491614 0.6426090556930975,1.0496337697385036 0.6888665424957445,1.0355119323187965 0.7358735770495916,1.0237136311333106 0.7835169152910685,1.0142672893230111 0.8316817802452878,1.0071956639527206 0.8802521385338314,1.0025157911873577 0.9291109799093207,1.0002389452503222 0.9781405991433534,1.000370611262905 1.0272228795887068,1.0029104720301485 1.0762395777326887,1.0078524088049996 1.1250726080561142,1.015184516028905 1.1736043275116659,1.0248891300133454 1.2217178189362987,1.0369428714932085 1.2692971727149267,1.0513167019494865 1.316227766016838,1.0679759935656108 1.3623965389321335,1.086880612648897 1.407692266842954,1.1079850163161244 1.4520058283733244,1.1312383622103312 1.495230468272109,1.1565846309845056 1.53726205459576,1.1839627612570998 1.5779993295712915,1.2133067967142457 1.617344153535124,1.2445460450042936 1.6552017413601288,1.2776052480418776 1.6914808908013024,1.3124047633112361 1.7260942022099632,1.3488607557320074 1.758958289087159,1.3868853996252821 1.7899939789690489,1.4263870902933562 1.8191265041603022,1.4672706647034706 1.8462856818560254,1.5094376307438928 1.8714060832182864,1.5527864045000421 1.8944271909999157,1.7639320225002106 2,1.5527864045000421 2.1055728090000843,1.5286032631740025 2.118078735651645,1.4858972558067784 2.1422713899997277,1.4444297669803978 2.1685303876974547,1.4043006955075668 2.196792468519355,1.3656067158363545 2.226989546637263,1.3284410451529816 2.259048874645041,1.2928932188134525 2.2928932188134525,1.2590488746450408 2.3284410451529816,1.2269895466372631 2.3656067158363543,1.1967924685193552 2.4043006955075668,1.1685303876974547 2.444429766980398,1.1422713899997279 2.4858972558067784,1.118078735651645 2.5286032631740025,1.0960107068765566 2.572444906569718,1.0761204674887133 2.6173165676349104,1.0584559348169793 2.66311014660778,1.043059664267791 2.709715322745538,1.029968746805456 2.757019820096736,1.0192147195967696 2.8049096779838716,1.0108234900352189 2.853269525544638,1.0048152733278033 2.9019828596704396,1.0012045437948276 2.950932325672582,1 3,1 5,1.0048152733278033 5.098017140329561,1.0108234900352189 5.146730474455362,1.0192147195967696 5.195090322016128,1.029968746805456 5.242980179903264,1.043059664267791 5.290284677254462,1.0584559348169793 5.33688985339222,1.0761204674887133 5.38268343236509,1.0960107068765566 5.427555093430282,1.118078735651645 5.471396736825998,1.1422713899997279 5.514102744193222,1.1685303876974547 5.555570233019602,1.1967924685193552 5.595699304492434,1.2269895466372631 5.634393284163646,1.2590488746450408 5.671558954847018,1.2928932188134525 5.707106781186548,1.3284410451529816 5.740951125354959,1.3656067158363545 5.773010453362737,1.4043006955075668 5.803207531480645,1.4444297669803978 5.831469612302545,1.4858972558067784 5.857728610000272,1.5286032631740025 5.881921264348355,1.572444906569718 5.903989293123443,1.6173165676349102 5.923879532511287,1.6631101466077798 5.941544065183021,1.7097153227455377 5.956940335732209,1.7570198200967362 5.970031253194544,1.8049096779838716 5.98078528040323,1.853269525544638 5.989176509964781,1.9019828596704393 5.995184726672197,1.950932325672582 5.998795456205173,2 6,2.049067674327418 5.998795456205173,2.0980171403295604 5.995184726672197,2.146730474455362 5.989176509964781,2.1950903220161284 5.98078528040323,2.242980179903264 5.970031253194544,2.290284677254462 5.956940335732209,2.33688985339222 5.941544065183021,2.3826834323650896 5.923879532511287,2.427555093430282 5.903989293123443,2.4713967368259975 5.881921264348355,2.5141027441932216 5.857728610000272,2.555570233019602 5.831469612302545,2.5956993044924332 5.803207531480645,2.6343932841636457 5.773010453362737,2.6715589548470184 5.740951125354959,2.7071067811865475 5.707106781186548,2.740951125354959 5.671558954847018,2.773010453362737 5.634393284163646,2.803207531480645 5.595699304492434,2.8314696123025453 5.555570233019602,2.8577286100002723 5.514102744193222,2.881921264348355 5.471396736825998,2.9039892931234434 5.427555093430282,2.923879532511287 5.38268343236509,2.9415440651830207 5.33688985339222,2.956940335732209 5.290284677254462,2.970031253194544 5.242980179903264,2.9807852804032304 5.195090322016128,2.989176509964781 5.146730474455362,2.9951847266721967 5.098017140329561,2.9987954562051726 5.049067674327418,3 5,3 3.618033988749895,4.447213595499958 2.8944271909999157,4.452005828373324 2.8920149836838753,4.4952304682721085 2.8687616377896688,4.53726205459576 2.8434153690154944,4.577999329571291 2.8160372387429002,4.617344153535124 2.786693203285754,4.655201741360129 2.7554539549957067,4.691480890801302 2.7223947519581224,4.726094202209963 2.6875952366887637,4.758958289087159 2.6511392442679926,4.789993978969049 2.613114600374718,4.819126504160303 2.573612909706644,4.846285681856025 2.5327293352965294,4.871406083218286 2.490562369256107,4.894427190999916 2.447213595499958,4.9152935453358575 2.402787445020965,4.933954877350839 2.3573909443069025,4.950366230261497 2.3111334575042557,4.964488067681204 2.2641264229504086,4.976286368866689 2.2164830847089316,4.985732710676989 2.1683182197547124,4.992804336047279 2.1197478614661684,4.997484208812643 2.070889020090679,4.999761054749678 2.0218594008566466,4.999629388737095 1.9727771204112932,4.997089527969852 1.9237604222673113,4.992147591195001 1.8749273919438858,4.984815483971095 1.8263956724883341,4.975110869986654 1.7782821810637013,4.963057128506792 1.7307028272850733,4.948683298050514 1.683772233983162,4.932024006434389 1.6376034610678665,4.913119387351103 1.592307733157046,4.892014983683875 1.5479941716266756,4.868761637789669 1.504769531727891,4.843415369015494 1.46273794540424,4.816037238742901 1.4220006704287085,4.786693203285754 1.382655846464876,4.755453954995707 1.3447982586398712,4.722394751958122 1.3085191091986976,4.687595236688764 1.2739057977900368,4.651139244267993 1.241041710912841,4.613114600374717 1.2100060210309511,4.573612909706644 1.1808734958396978,4.53272933529653 1.1537143181439746,4.490562369256107 1.1285939167817136,4.447213595499958 1.1055728090000843,2.447213595499958 0.10557280900008414,2.3573909443069025 0.06604512264916129,2.3111334575042557 0.04963376973850353,2.2641264229504086 0.03551193231879646,2.2164830847089316 0.023713631133310598,2.1683182197547124 0.014267289323011023,2.1197478614661684 0.007195663952720532,2.070889020090679 0.0025157911873575634,2.0218594008566466 0.00023894525032219782))
+DROP TABLE t1;
+select st_touches(geomfromtext('point(0 0)'), geomfromtext('point(1 1)'));
+st_touches(geomfromtext('point(0 0)'), geomfromtext('point(1 1)'))
+0
+select st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 1)'));
+st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 1)'))
+1
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 1)'));
+st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 1)'))
+1
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)'));
+st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)'))
+0
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 2)'));
+st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 2)'))
+0
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1.2, 1 0, 2 0, 1 1.2))'));
+st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1.2, 1 0, 2 0, 1 1.2))'))
+1
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))'));
+st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))'))
+1
+SELECT ST_Equals(PolyFromText('POLYGON((67 13, 67 18, 67 18, 59 18, 59 13, 67 13) )'),PolyFromText('POLYGON((67 13, 67 18, 59 19, 59 13, 59 13, 67 13) )')) as result;
+result
+0
+SELECT ST_Equals(PolyFromText('POLYGON((67 13, 67 18, 67 18, 59 18, 59 13, 67 13) )'),PolyFromText('POLYGON((67 13, 67 18, 59 18, 59 13, 59 13, 67 13) )')) as result;
+result
+1
+SELECT ST_Equals(PointFromText('POINT (12 13)'),PointFromText('POINT (12 13)')) as result;
+result
+1
+SELECT astext(ST_UNION (
+PolyFromText('POLYGON(( 2 2 ,3 2,2 7,2 2),( 0 0,8 2,1 9,0 0))'),
+ExteriorRing( Envelope( MultiLineStringFromText('MULTILINESTRING((3 4,5 3),(3 0,0 5))')))));
+astext(ST_UNION (
+PolyFromText('POLYGON(( 2 2 ,3 2,2 7,2 2),( 0 0,8 2,1 9,0 0))'),
+ExteriorRing( Envelope( MultiLineStringFromText('MULTILINESTRING((3 4,5 3),(3 0,0 5))')))))
+GEOMETRYCOLLECTION(POLYGON((0 0,1 9,8 2,0 0),(2 2,2 7,3 2,2 2)),LINESTRING(0.5555555555555556 5,0 5,0 0,5 0,5 1.25),LINESTRING(2 5,2.4 5))
+SELECT astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0));
+astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0))
+LINESTRING(0 0,1 1)
+SELECT Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), 3)), 5);
+Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), 3)), 5)
+78.68426
+SELECT ST_INTERSECTION(NULL, NULL);
+ST_INTERSECTION(NULL, NULL)
+NULL
+SELECT ASTEXT(ST_INTERSECTION(
+MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4)),
+ ((0 5,3 5,3 0,0 0,0 1,2 1,2 2,0 2,0 5), (1 3,2 3,2 4,1 4,1 3)),
+ ((2 2,5 2,4 4,2 8,2 2)))'),
+MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((3 5,2 4,2 5,3 5)),
+ ((2 2,9 2,0 2,2 6,2 2)),
+ ((2 2,2 8,8 8,8 2,2 2), (4 4,4 6,6 6,6 4,4 4)),
+ ((9 9,6 8,7 0,9 9)))')));
+ASTEXT(ST_INTERSECTION(
+MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4)),
+ ((0 5,3 5,3 0,0 0,0 1,2 1,2 2,0 2,0 5), (1 3,2 3,2 4,1 4,1 3)),
+ ((2 2,5 2,4 4,2 8,2 2)))'),
+MULTIPOLY
+POLYGON((0 2,1 4,1 3,2 3,2 4,1 4,1.5 5,2 5,2 8,8 8,8 2,0 2),(4 4,4 6,6 6,6 4,4 4))
+SELECT ASTEXT(ST_UNION(
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((6 2,4 0,3 5,3 6,4 3,6 4,3 9,0 7,3 7,8 4,2 9,5 0),
+ (8 2,1 3,9 0,4 4))'),
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((2 5,6 7,9 7,5 2,1 6,3 6))')));
+ASTEXT(ST_UNION(
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((6 2,4 0,3 5,3 6,4 3,6 4,3 9,0 7,3 7,8 4,2 9,5 0),
+ (8 2,1 3,9 0,4 4))'),
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((2 5,6 7,9 7,5 2,1 6,3 6))')))
+MULTILINESTRING((3.5945945945945947 2.027027027027027,4 0,4.75 0.75),(5 0,4.75 0.75),(5.363636363636363 1.3636363636363635,9 0,6.173913043478262 2.260869565217391),(4.75 0.75,4.428571428571429 1.7142857142857142),(4.75 0.75,5.363636363636363 1.3636363636363635),(5.363636363636363 1.3636363636363635,4.428571428571429 1.7142857142857142),(5.363636363636363 1.3636363636363635,6 2),(4.428571428571429 1.7142857142857142,3.5945945945945947 2.027027027027027),(4.428571428571429 1.7142857142857142,4.15 2.55),(4.5 2.5,5 2,5.3076923076923075 2.3846153846153846),(8 2,6.173913043478262 2.260869565217391),(3.5945945945945947 2.027027027027027,1 3,3.4705882352941178 2.6470588235294117),(3.5945945945945947 2.027027027027027,3.4705882352941178 2.6470588235294117),(6.173913043478262 2.260869565217391,5.3076923076923075 2.3846153846153846),(6.173913043478262 2.260869565217391,5.585365853658536 2.7317073170731705),(5.3076923076923075 2.3846153846153846,4.5 2.5),(5.3076923076923075 2.3846153846153846,5.585365853658536 2.7317073170731705),(4.5 2.5,4.15 2.55),(4.5 2.5,4 3),(4.15 2.55,3.4705882352941178 2.6470588235294117),(4.15 2.55,4 3),(3.4705882352941178 2.6470588235294117,3.25 3.75),(5.585365853658536 2.7317073170731705,4.769230769230769 3.3846153846153846),(5.585365853658536 2.7317073170731705,7.054054054054054 4.5675675675675675),(4 3,3.25 3.75),(4 3,3.142857142857143 5.571428571428571),(4 3,4.769230769230769 3.3846153846153846),(4.769230769230769 3.3846153846153846,4 4),(4.769230769230769 3.3846153846153846,6 4,4.875 5.875),(3.25 3.75,2 5),(3.25 3.75,3 5,3 5.5),(7.054054054054054 4.5675675675675675,8 4,7.16 4.7),(7.054054054054054 4.5675675675675675,4.875 5.875),(7.054054054054054 4.5675675675675675,7.16 4.7),(7.16 4.7,5 6.5),(7.16 4.7,9 7,6 7,5 6.5),(2 5,1 6,3 6),(2 5,3 5.5),(3 5.5,3 6),(3 5.5,3.142857142857143 5.571428571428571),(3.142857142857143 5.571428571428571,3 6),(3.142857142857143 5.571428571428571,4.363636363636363 6.181818181818182),(4.875 5.875,4.363636363636363 6.181818181818182),(4.875 5.875,4.615384615384615 6.3076923076923075),(3 6,2.6666666666666665 7),(4.363636363636363 6.181818181818182,3 7,2.6666666666666665 7),(4.363636363636363 6.181818181818182,4.615384615384615 6.3076923076923075),(4.615384615384615 6.3076923076923075,4 7.333333333333333),(4.615384615384615 6.3076923076923075,5 6.5),(5 6.5,4 7.333333333333333),(2.1818181818181817 8.454545454545455,0 7,2.6666666666666665 7),(2.6666666666666665 7,2.1818181818181817 8.454545454545455),(4 7.333333333333333,2.444444444444444 8.62962962962963),(4 7.333333333333333,3 9,2.444444444444444 8.62962962962963),(2.1818181818181817 8.454545454545455,2 9,2.444444444444444 8.62962962962963),(2.1818181818181817 8.454545454545455,2.444444444444444 8.62962962962963))
+SELECT ST_NUMGEOMETRIES((ST_UNION(ST_UNION(
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((2 0,4 2,0 2,1 5,0 3,7 0,8 5,5 8),
+ (6 2,4 0,3 5,3 6,4 3,6 4,3 9,0 7,3 7,8 4,2 9,5 0),
+ (7 8,3 1,0 9,6 0,4 8),
+ (9 3,0 4,5 9,6 4),
+ (8 2,1 3,9 0,4 4))'),
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((6 0,9 3,2 5,3 6,3 2),
+ (2 5,6 7,9 7,5 2,1 6,3 6))')),
+MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((7 7,3 7,3 1,7 8,7 7)),
+ ((3 5,2 4,2 5,3 5)),
+ ((7 7,8 7,3 7,7 7,7 7)),
+ ((0 5,3 5,3 4,1 4,1 3,3 3,3 0,0 0,0 5), (1 1,2 1,2 2,1 2,1 1)))'))));
+ST_NUMGEOMETRIES((ST_UNION(ST_UNION(
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((2 0,4 2,0 2,1 5,0 3,7 0,8 5,5 8),
+ (6 2,4 0,3 5,3 6,4 3,6 4,3 9,0 7,3 7,8 4,2 9,5 0),
+
+192
+SELECT Round(ST_AREA(ST_BUFFER( ST_UNION(
+POLYGONFROMTEXT('POLYGON((7 7, 7 7, 7 4, 7 7, 7 7))'),
+POLYGONFROMTEXT('POLYGON((7 7, 4 7, 2 9, 7 6, 7 7))')), 1)), 6);
+Round(ST_AREA(ST_BUFFER( ST_UNION(
+POLYGONFROMTEXT('POLYGON((7 7, 7 7, 7 4, 7 7, 7 7))'),
+POLYGONFROMTEXT('POLYGON((7 7, 4 7, 2 9, 7 6, 7 7))')), 1)), 6)
+21.901344
+SELECT AsText(ST_UNION(MultiPolygonFromText('
+ MULTIPOLYGON(((2 2, 2 8, 8 8, 8 2, 2 2), (4 4, 4 6, 6 6, 6 4, 4 4)),
+ ((0 0, 8 3, 7 4, 0 0)),
+ ((2 2, 2 8, 8 8, 8 2, 2 2), (4 4, 4 6, 6 6, 6 4, 4 4)))'),
+MultiPolygonFromText(' MULTIPOLYGON(((0 0, 1 9, 4 6, 0 0)),
+ ((0 5, 3 5, 3 4, 1 4, 1 3, 3 3, 3 0, 0 0, 0 5), (1 1, 2 1, 2 2, 1 2, 1 1)),
+ ((7 7, 4 7, 6 3, 7 2, 7 7)),
+ ((0 5, 3 5, 3 4, 1 4, 1 3, 3 3, 3 0, 0 0, 0 5), (1 1, 2 1, 2 2, 1 2, 1 1))) ')));
+AsText(ST_UNION(MultiPolygonFromText('
+ MULTIPOLYGON(((2 2, 2 8, 8 8, 8 2, 2 2), (4 4, 4 6, 6 6, 6 4, 4 4)),
+ ((0 0, 8 3, 7 4, 0 0)),
+ ((2 2, 2 8, 8 8, 8 2, 2 2), (4 4, 4 6, 6 6, 6 4, 4 4)))'),
+MultiPolygonFr
+POLYGON((0 0,0 5,0.5555555555555556 5,1 9,2 8,8 8,8 2,5.333333333333334 2,3 1.125,3 0,0 0),(1 1,1 1.5,1.3333333333333333 2,2 2,2 1.1428571428571428,1.75 1,1 1),(3 1.7142857142857142,3 2,3.5 2,3 1.7142857142857142),(4 4,4 6,4.5 6,5.5 4,4 4))
+SELECT AsText(ST_SYMDIFFERENCE(
+MultiLineStringFromText('MULTILINESTRING((7 7, 1 7, 8 5, 7 8, 7 7),
+ (6 3, 3 4, 1 1, 9 9, 9 0, 8 4, 9 9))'),
+Envelope(GeometryFromText('MULTIPOINT(7 9, 0 0, 3 7, 1 6, 0 0)'))));
+AsText(ST_SYMDIFFERENCE(
+MultiLineStringFromText('MULTILINESTRING((7 7, 1 7, 8 5, 7 8, 7 7),
+ (6 3, 3 4, 1 1, 9 9, 9 0, 8 4, 9 9))'),
+Envelope(GeometryFromText('MULTIPOINT(7 9, 0 0, 3 7, 1 6, 0 0)'))))
+GEOMETRYCOLLECTION(POLYGON((0 0,0 9,7 9,7 0,0 0)),LINESTRING(9 9,8 4,9 0,9 9),LINESTRING(7 5.285714285714286,8 5,7.25 7.25),LINESTRING(7 7,7.25 7.25),LINESTRING(7.25 7.25,7 8),LINESTRING(7.25 7.25,9 9))
+SELECT AsText(ST_UNION(
+MultiPolygonFromText('MULTIPOLYGON(((9 9, 7 9, 1 1, 9 9)),
+ ((2 2, 1 2, 3 3, 2 2, 2 2)),
+ ((0 0, 7 5, 9 6, 0 0)),
+ ((7 7, 5 7, 1 5, 7 1, 7 7)))'),
+MultiPolygonFromText('MULTIPOLYGON(((2 2, 2 2, 1 5, 2 7, 2 2)),
+ ((0 5, 3 5, 3 0, 0 0, 0 5), (1 1, 2 1, 2 4, 1 4, 1 1)))')));
+AsText(ST_UNION(
+MultiPolygonFromText('MULTIPOLYGON(((9 9, 7 9, 1 1, 9 9)),
+ ((2 2, 1 2, 3 3, 2 2, 2 2)),
+ ((0 0, 7 5, 9 6, 0 0)),
+
+POLYGON((0 0,0 5,1 5,2 7,2 5.5,5 7,5.5 7,7 9,9 9,7 7,7 5,9 6,7 4.666666666666667,7 1,4.25 2.833333333333333,3 2,3 0,0 0),(1 1,1 4,1.3333333333333333 4,1.8571428571428572 2.4285714285714284,1 2,1.75 2,1 1,2 2,2 1.4285714285714284,1.4 1,1 1),(1.5 1,2 1.3333333333333333,2 1,1.5 1),(3 2.142857142857143,3 3,3.4 3.4,4.1034482758620685 2.9310344827586206,3 2.142857142857143))
+SELECT AsText( ST_INTERSECTION(
+LinestringFromText('LINESTRING( 3 5, 2 5, 2 4, 3 4, 3 5 ) ') ,
+LinestringFromText('LINESTRING( 3 5, 2 4, 2 5, 3 5 ) ')
+));
+AsText( ST_INTERSECTION(
+LinestringFromText('LINESTRING( 3 5, 2 5, 2 4, 3 4, 3 5 ) ') ,
+LinestringFromText('LINESTRING( 3 5, 2 4, 2 5, 3 5 ) ')
+))
+LINESTRING(2 4,2 5,3 5)
+SELECT AsText( ST_UNION(
+PolygonFromText(' POLYGON( ( 2 2 , 3 2 , 7 5 , 2 0 , 2 2 ) ) ') ,
+PolygonFromText(' POLYGON( ( 2 2 , 3 2 , 3 3 , 2 5 , 2 2 ) ) ') ) );
+AsText( ST_UNION(
+PolygonFromText(' POLYGON( ( 2 2 , 3 2 , 7 5 , 2 0 , 2 2 ) ) ') ,
+PolygonFromText(' POLYGON( ( 2 2 , 3 2 , 3 3 , 2 5 , 2 2 ) ) ') ) )
+POLYGON((2 0,2 5,3 3,3 2,7 5,2 0))
+SELECT AsText(ST_INTERSECTION(LinestringFromText('LINESTRING(1 1, 2 2)'), GeometryFromText('LINESTRING(3 3, 4 4)')));
+AsText(ST_INTERSECTION(LinestringFromText('LINESTRING(1 1, 2 2)'), GeometryFromText('LINESTRING(3 3, 4 4)')))
+GEOMETRYCOLLECTION EMPTY
+SELECT AsText(ST_UNION(GEOMETRYFROMTEXT('POINT(8 1)') ,MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 5, 2 5, 2 4, 3 4, 3 5))')));
+AsText(ST_UNION(GEOMETRYFROMTEXT('POINT(8 1)') ,MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 5, 2 5, 2 4, 3 4, 3 5))')))
+GEOMETRYCOLLECTION(POINT(8 1),LINESTRING(2 4,2 5,3 5,3 4,2 4))
+SELECT ST_DISTANCE(POINTFROMTEXT('POINT(7 1)'),MULTILINESTRINGFROMTEXT('MULTILINESTRING(
+ (4 7,9 7,6 1,3 4,1 1), (3 5, 2 5, 2 4, 3 4, 3 5))'));
+ST_DISTANCE(POINTFROMTEXT('POINT(7 1)'),MULTILINESTRINGFROMTEXT('MULTILINESTRING(
+ (4 7,9 7,6 1,3 4,1 1), (3 5, 2 5, 2 4, 3 4, 3 5))'))
+1
+SELECT AsText(ST_UNION(POLYGONFROMTEXT('POLYGON((12 9, 3 6, 3 0, 12 9))'), POLYGONFROMTEXT('POLYGON((2 2, 7 2, 4 2, 2 0, 2 2))')));
+AsText(ST_UNION(POLYGONFROMTEXT('POLYGON((12 9, 3 6, 3 0, 12 9))'), POLYGONFROMTEXT('POLYGON((2 2, 7 2, 4 2, 2 0, 2 2))')))
+GEOMETRYCOLLECTION(POLYGON((2 0,2 2,3 2,3 6,12 9,3 0,3 1,2 0)),LINESTRING(5 2,7 2))
+SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER(ST_UNION(
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 2 5, 7 6, 1 8),(0 0 ,1 6 ,0 1, 8 9, 2 4, 6 1, 3 5, 4 8), (9 3, 5 4, 1 8, 4 2, 5 8, 3 0))' ) ,
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 3 1, 2 7, 4 2, 6 2, 1 5))')
+), 16)));
+ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER(ST_UNION(
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 2 5, 7 6, 1 8),(0 0 ,1 6 ,0 1, 8 9, 2 4, 6 1, 3 5, 4 8), (9 3, 5 4, 1 8, 4 2, 5 8, 3 0))' ) ,
+MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 3 1, 2 7, 4 2, 6 2
+278
+SELECT ST_NUMGEOMETRIES(ST_DIFFERENCE (
+ST_UNION (
+MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 4 , 5 0 , 2 9 , 6 2 , 0 2 ) , ( 4 3 , 5 6 , 9 4 , 0 7 , 7 2 , 2 0 , 8 2 ) , ( 5 0 , 1 5 , 3 7 , 7 7 ) , ( 2 3 , 9 5 , 2 0 , 8 1 ) , ( 0 9 , 9 3 , 2 8 , 8 1 , 9 4 ) ) ' ),
+ST_UNION (
+MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 7 2 , 6 2 , 2 6 , 2 2 ) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) ,
+ENVELOPE(
+MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' )
+)
+)
+),
+MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 9 , 1 3 , 7 3 , 8 5 ) , ( 5 0 , 8 1 , 2 0 , 7 4 , 1 0 ) , ( 9 2 , 5 2 , 6 5 , 8 8 , 0 2 ) , ( 0 8 , 3 9 , 4 0 , 1 0 ) , ( 0 0 , 7 6 , 8 3 , 0 0 ) ) ' )
+));
+ST_NUMGEOMETRIES(ST_DIFFERENCE (
+ST_UNION (
+MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 4 , 5 0 , 2 9 , 6 2 , 0 2 ) , ( 4 3 , 5 6 , 9 4 , 0 7 , 7 2 , 2 0 , 8 2 ) , ( 5 0 , 1 5 , 3 7 , 7 7 ) , ( 2 3 , 9 5 , 2 0 , 8 1 ) , ( 0 9 , 9 3 , 2 8 , 8 1 , 9 4 )
+125
+SELECT ASTEXT(ST_DIFFERENCE (
+POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) ,
+ST_UNION (
+MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ' ) ,
+ST_SYMDIFFERENCE (
+MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 3 8 , 0 8 , 6 6 , 6 1 , 0 5 , 6 7 , 3 7 ) , ( 5 8 , 7 7 , 9 0 , 8 7 ) , ( 1 5 , 1 8 , 2 3 , 3 9 ) , ( 1 3 , 9 7 , 5 5 , 0 8 , 6 9 ) , ( 3 6 , 6 9 , 8 7 , 0 2 , 4 6 , 9 5 ) ) ' ) ,
+ST_UNION (
+MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 9 4 , 2 0 , 2 2 , 7 2 , 6 2 ) , ( 5 2 , 8 2 , 4 8 , 3 4 ) , ( 1 0 , 1 4 , 2 7 , 7 0 , 1 5 ) , ( 2 8 , 4 4 , 5 0 , 7 0 , 4 0 ) ) ' ) ,
+GEOMETRYFROMTEXT( ' MULTILINESTRING( ( 3 7 , 7 3 , 5 8 , 4 8 ) , ( 3 2 , 5 0 , 9 3 , 4 4 ) , ( 6 0 , 4 2 , 7 8 , 1 3 ) ) ' )
+)
+)
+)
+));
+ASTEXT(ST_DIFFERENCE (
+POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) ,
+ST_UNION (
+MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ' ) ,
+ST_SYMDIFFERENCE (
+MULTILINESTRINGFROMTEX
+POLYGON((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4))
+SELECT ST_NUMGEOMETRIES(ST_UNION (
+MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 0 8 , 1 9 , 5 7 , 2 8 , 5 8 , 6 7 ) , ( 4 5 , 8 4 , 0 3 , 5 1 ) , ( 6 8 , 2 7 , 1 6 , 9 9 , 7 2 ) , ( 9 5 , 2 8 , 1 2 , 9 6 , 2 0 ) ) ' ) ,
+MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 7 7 , 2 7, 6 8, 7 1 , 7 7 ) ) ) ' )
+));
+ST_NUMGEOMETRIES(ST_UNION (
+MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 0 8 , 1 9 , 5 7 , 2 8 , 5 8 , 6 7 ) , ( 4 5 , 8 4 , 0 3 , 5 1 ) , ( 6 8 , 2 7 , 1 6 , 9 9 , 7 2 ) , ( 9 5 , 2 8 , 1 2 , 9 6 , 2 0 ) ) ' ) ,
+MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (
+50
+SELECT ST_BUFFER (
+LINESTRINGFROMTEXT( ' LINESTRING( 5 4 , 3 8 , 2 6 , 5 5 , 7 9 ) ' ) ,
+ST_DISTANCE (
+MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ,
+ST_DIFFERENCE (
+MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) ,
+MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' )
+)
+)
+) ;
+ST_BUFFER (
+LINESTRINGFROMTEXT( ' LINESTRING( 5 4 , 3 8 , 2 6 , 5 5 , 7 9 ) ' ) ,
+ST_DISTANCE (
+MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ,
+ST_DIFFERENCE (
+MULTIPOL
+NULL
+SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ;
+ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 ,
+NULL
+SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') ));
+ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5))
+MULTIPOINT(7 5,7 5.142857142857142,5.899999999999998 5.300000000000001,5.799999999999997 5.600000000000001,3 7)
+SELECT ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) '));
+ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) '))
+0
+SELECT ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') );
+ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') )
+0
+SELECT ST_WITHIN( POINTFROMTEXT(' POINT(1 2 ) ') , MULTIPOLYGONFROMTEXT(' MULTIPOLYGON( ( (0 5, 3 5, 3 0, 0 0, 0 5), ( 1 1 , 2 1 , 2 4, 1 4, 1 1 ) ) ) '));
+ST_WITHIN( POINTFROMTEXT(' POINT(1 2 ) ') , MULTIPOLYGONFROMTEXT(' MULTIPOLYGON( ( (0 5, 3 5, 3 0, 0 0, 0 5), ( 1 1 , 2 1 , 2 4, 1 4, 1 1 ) ) ) '))
+1
+select ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY')));
+ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY')))
+GEOMETRYCOLLECTION EMPTY
+SELECT ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') );
+ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') )
+0
+SELECT ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') );
+ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') )
+0
+SELECT ST_EQUALS( MULTIPOINTFROMTEXT(' MULTIPOINT( 5 1 , 6 9 , 1 4 , 4 0 ) ') , MULTIPOINTFROMTEXT(' MULTIPOINT( 5 8 , 5 2 , 1 8 , 3 0 , 3 0 , 7 8 ) ') );
+ST_EQUALS( MULTIPOINTFROMTEXT(' MULTIPOINT( 5 1 , 6 9 , 1 4 , 4 0 ) ') , MULTIPOINTFROMTEXT(' MULTIPOINT( 5 8 , 5 2 , 1 8 , 3 0 , 3 0 , 7 8 ) ') )
+0
+SELECT ST_EQUALS( MULTIPOINTFROMTEXT(' MULTIPOINT( 5 1 , 6 9 , 1 4 , 4 0 ) ') , MULTIPOINTFROMTEXT('MULTIPOINT( 4 0 , 6 9 , 5 1, 1 4 )') );
+ST_EQUALS( MULTIPOINTFROMTEXT(' MULTIPOINT( 5 1 , 6 9 , 1 4 , 4 0 ) ') , MULTIPOINTFROMTEXT('MULTIPOINT( 4 0 , 6 9 , 5 1, 1 4 )') )
+1
+SELECT ST_WITHIN( MULTIPOINTFROMTEXT(' MULTIPOINT( 2 9 , 2 9 , 4 9 , 9 1 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) '));
+ST_WITHIN( MULTIPOINTFROMTEXT(' MULTIPOINT( 2 9 , 2 9 , 4 9 , 9 1 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) '))
+0
+SELECT ST_INTERSECTS( GeomFromText('MULTILINESTRING( ( 4030 3045 , 3149 2461 , 3004 3831 , 3775 2976 ) )') , GeomFromText('LINESTRING(3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29,3039.07 3175.05,3039.07 3175.05,3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29)') );
+ST_INTERSECTS( GeomFromText('MULTILINESTRING( ( 4030 3045 , 3149 2461 , 3004 3831 , 3775 2976 ) )') , GeomFromText('LINESTRING(3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29,3039.07 3175.05,3039.07 3175.05,3058.41 3187.91,3081.52 3153.19,
+1
diff --git a/mysql-test/r/gis-rt-precise.result b/mysql-test/r/gis-rt-precise.result
new file mode 100644
index 00000000000..4519dcb6d19
--- /dev/null
+++ b/mysql-test/r/gis-rt-precise.result
@@ -0,0 +1,49 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (
+fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+g GEOMETRY NOT NULL,
+SPATIAL KEY(g)
+) ENGINE=MyISAM;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `fid` int(11) NOT NULL AUTO_INCREMENT,
+ `g` geometry NOT NULL,
+ PRIMARY KEY (`fid`),
+ SPATIAL KEY `g` (`g`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT count(*) FROM t1;
+count(*)
+150
+EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE ST_Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 140))'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range g g 34 NULL 8 Using where
+SELECT fid, AsText(g) FROM t1 WHERE ST_Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
+fid AsText(g)
+11 LINESTRING(140 140,160 160)
+DROP TABLE t1;
+CREATE TABLE t1 (
+fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+g GEOMETRY NOT NULL
+) ENGINE=MyISAM;
+ALTER TABLE t1 ADD SPATIAL KEY(g);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `fid` int(11) NOT NULL AUTO_INCREMENT,
+ `g` geometry NOT NULL,
+ PRIMARY KEY (`fid`),
+ SPATIAL KEY `g` (`g`)
+) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=latin1
+SELECT count(*) FROM t1;
+count(*)
+100
+EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE ST_Within(g,
+GeomFromText('Polygon((40 40,60 40,60 60,40 40))'));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range g g 34 NULL 1 Using where
+SELECT fid, AsText(g) FROM t1 WHERE ST_Within(g,
+GeomFromText('Polygon((40 40,60 40,60 60,40 40))'));
+fid AsText(g)
+DROP TABLE t1;
+End of 5.5 tests.
diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index 6db63a6ada0..a1c3f274ed3 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -12,6 +12,156 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`fid`),
SPATIAL KEY `g` (`g`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(150 150, 150 150)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(149 149, 151 151)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(148 148, 152 152)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(147 147, 153 153)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(146 146, 154 154)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(145 145, 155 155)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(144 144, 156 156)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(143 143, 157 157)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(142 142, 158 158)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(141 141, 159 159)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(140 140, 160 160)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(139 139, 161 161)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(138 138, 162 162)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(137 137, 163 163)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(136 136, 164 164)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(135 135, 165 165)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(134 134, 166 166)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(133 133, 167 167)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(132 132, 168 168)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(131 131, 169 169)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(130 130, 170 170)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(129 129, 171 171)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(128 128, 172 172)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(127 127, 173 173)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(126 126, 174 174)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(125 125, 175 175)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(124 124, 176 176)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(123 123, 177 177)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(122 122, 178 178)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(121 121, 179 179)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(120 120, 180 180)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(119 119, 181 181)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(118 118, 182 182)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(117 117, 183 183)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(116 116, 184 184)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(115 115, 185 185)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(114 114, 186 186)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(113 113, 187 187)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(112 112, 188 188)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(111 111, 189 189)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(110 110, 190 190)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(109 109, 191 191)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(108 108, 192 192)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(107 107, 193 193)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(106 106, 194 194)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(105 105, 195 195)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(104 104, 196 196)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(103 103, 197 197)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(102 102, 198 198)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(101 101, 199 199)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(100 100, 200 200)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(99 99, 201 201)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(98 98, 202 202)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(97 97, 203 203)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(96 96, 204 204)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(95 95, 205 205)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(94 94, 206 206)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(93 93, 207 207)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(92 92, 208 208)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(91 91, 209 209)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(90 90, 210 210)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(89 89, 211 211)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(88 88, 212 212)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(87 87, 213 213)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(86 86, 214 214)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(85 85, 215 215)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(84 84, 216 216)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(83 83, 217 217)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(82 82, 218 218)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(81 81, 219 219)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(80 80, 220 220)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(79 79, 221 221)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(78 78, 222 222)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(77 77, 223 223)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(76 76, 224 224)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(75 75, 225 225)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(74 74, 226 226)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(73 73, 227 227)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(72 72, 228 228)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(71 71, 229 229)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(70 70, 230 230)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(69 69, 231 231)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(68 68, 232 232)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(67 67, 233 233)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(66 66, 234 234)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(65 65, 235 235)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(64 64, 236 236)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(63 63, 237 237)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(62 62, 238 238)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(61 61, 239 239)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(60 60, 240 240)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(59 59, 241 241)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(58 58, 242 242)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(57 57, 243 243)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(56 56, 244 244)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(55 55, 245 245)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(54 54, 246 246)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(53 53, 247 247)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(52 52, 248 248)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(51 51, 249 249)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(50 50, 250 250)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(49 49, 251 251)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(48 48, 252 252)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(47 47, 253 253)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(46 46, 254 254)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(45 45, 255 255)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(44 44, 256 256)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(43 43, 257 257)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(42 42, 258 258)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(41 41, 259 259)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(40 40, 260 260)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(39 39, 261 261)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(38 38, 262 262)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(37 37, 263 263)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(36 36, 264 264)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(35 35, 265 265)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(34 34, 266 266)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(33 33, 267 267)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(32 32, 268 268)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(31 31, 269 269)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(30 30, 270 270)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(29 29, 271 271)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(28 28, 272 272)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(27 27, 273 273)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(26 26, 274 274)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(25 25, 275 275)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(24 24, 276 276)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(23 23, 277 277)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(22 22, 278 278)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(21 21, 279 279)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(20 20, 280 280)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(19 19, 281 281)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(18 18, 282 282)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(17 17, 283 283)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(16 16, 284 284)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(15 15, 285 285)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(14 14, 286 286)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(13 13, 287 287)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(12 12, 288 288)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(11 11, 289 289)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(10 10, 290 290)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(9 9, 291 291)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(8 8, 292 292)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(7 7, 293 293)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(6 6, 294 294)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(5 5, 295 295)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(4 4, 296 296)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(3 3, 297 297)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(2 2, 298 298)'));
+INSERT INTO t1 (g) VALUES (GeomFromText('LineString(1 1, 299 299)'));
SELECT count(*) FROM t1;
count(*)
150
@@ -20,22 +170,112 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range g g 34 NULL 8 Using where
SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
fid AsText(g)
-1 LINESTRING(150 150,150 150)
-3 LINESTRING(148 148,152 152)
-4 LINESTRING(147 147,153 153)
-5 LINESTRING(146 146,154 154)
-6 LINESTRING(145 145,155 155)
-7 LINESTRING(144 144,156 156)
-8 LINESTRING(143 143,157 157)
-9 LINESTRING(142 142,158 158)
-10 LINESTRING(141 141,159 159)
11 LINESTRING(140 140,160 160)
-2 LINESTRING(149 149,151 151)
DROP TABLE t1;
CREATE TABLE t2 (
fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
g GEOMETRY NOT NULL
) ENGINE=MyISAM;
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10)));
+INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10)));
ALTER TABLE t2 ADD SPATIAL KEY(g);
SHOW CREATE TABLE t2;
Table Create Table
@@ -51,212 +291,408 @@ count(*)
EXPLAIN SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range g g 34 NULL 4 Using where
+1 SIMPLE t2 range g g 34 NULL 1 Using where
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
fid AsText(g)
-46 LINESTRING(51 41,60 50)
-56 LINESTRING(41 41,50 50)
-45 LINESTRING(51 51,60 60)
-55 LINESTRING(41 51,50 60)
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
+DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10))));
+SELECT count(*) FROM t2;
count(*)
100
DROP TABLE t2;
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 40007dd3a05..58cc47bdc18 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -66,7 +66,9 @@ INSERT INTO gis_multi_polygon VALUES
(119, MPolyFromWKB(AsWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))));
INSERT INTO gis_geometrycollection VALUES
(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')),
-(121, GeometryFromWKB(AsWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))));
+(121, GeometryFromWKB(AsWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))))),
+(122, GeomFromText('GeometryCollection()')),
+(123, GeomFromText('GeometryCollection EMPTY'));
INSERT into gis_geometry SELECT * FROM gis_point;
INSERT into gis_geometry SELECT * FROM gis_line;
INSERT into gis_geometry SELECT * FROM gis_polygon;
@@ -109,6 +111,8 @@ SELECT fid, AsText(g) FROM gis_geometrycollection;
fid AsText(g)
120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
+122 GEOMETRYCOLLECTION EMPTY
+123 GEOMETRYCOLLECTION EMPTY
SELECT fid, AsText(g) FROM gis_geometry;
fid AsText(g)
101 POINT(10 10)
@@ -132,6 +136,8 @@ fid AsText(g)
119 MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
+122 GEOMETRYCOLLECTION EMPTY
+123 GEOMETRYCOLLECTION EMPTY
SELECT fid, Dimension(g) FROM gis_geometry;
fid Dimension(g)
101 0
@@ -155,6 +161,8 @@ fid Dimension(g)
119 2
120 1
121 1
+122 0
+123 0
SELECT fid, GeometryType(g) FROM gis_geometry;
fid GeometryType(g)
101 POINT
@@ -178,6 +186,8 @@ fid GeometryType(g)
119 MULTIPOLYGON
120 GEOMETRYCOLLECTION
121 GEOMETRYCOLLECTION
+122 GEOMETRYCOLLECTION
+123 GEOMETRYCOLLECTION
SELECT fid, IsEmpty(g) FROM gis_geometry;
fid IsEmpty(g)
101 0
@@ -201,6 +211,8 @@ fid IsEmpty(g)
119 0
120 0
121 0
+122 0
+123 0
SELECT fid, AsText(Envelope(g)) FROM gis_geometry;
fid AsText(Envelope(g))
101 POLYGON((10 10,10 10,10 10,10 10,10 10))
@@ -224,11 +236,13 @@ fid AsText(Envelope(g))
119 POLYGON((0 0,3 0,3 3,0 3,0 0))
120 POLYGON((0 0,10 0,10 10,0 10,0 0))
121 POLYGON((3 6,44 6,44 9,3 9,3 6))
+122 GEOMETRYCOLLECTION EMPTY
+123 GEOMETRYCOLLECTION EMPTY
explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 100.00
+1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 23 100.00
Warnings:
-Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry`
+Note 1003 select st_dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,st_geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,st_isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,st_astext(st_envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry`
SELECT fid, X(g) FROM gis_point;
fid X(g)
101 10
@@ -245,7 +259,7 @@ explain extended select X(g),Y(g) FROM gis_point;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 100.00
Warnings:
-Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point`
+Note 1003 select st_x(`test`.`gis_point`.`g`) AS `X(g)`,st_y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point`
SELECT fid, AsText(StartPoint(g)) FROM gis_line;
fid AsText(StartPoint(g))
105 POINT(0 0)
@@ -280,7 +294,7 @@ explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),Num
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line`
+Note 1003 select st_astext(st_startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,st_astext(st_endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,st_length(`test`.`gis_line`.`g`) AS `GLength(g)`,st_numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,st_astext(st_pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,st_isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line`
SELECT fid, AsText(Centroid(g)) FROM gis_polygon;
fid AsText(Centroid(g))
108 POINT(15 15)
@@ -310,7 +324,7 @@ explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumI
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon`
+Note 1003 select st_astext(st_centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,st_area(`test`.`gis_polygon`.`g`) AS `Area(g)`,st_astext(st_exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,st_numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,st_astext(st_interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon`
SELECT fid, IsClosed(g) FROM gis_multi_line;
fid IsClosed(g)
114 0
@@ -345,11 +359,13 @@ SELECT fid, NumGeometries(g) from gis_geometrycollection;
fid NumGeometries(g)
120 2
121 2
+122 0
+123 0
explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point`
+Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,st_numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point`
SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
fid AsText(GeometryN(g, 2))
111 POINT(10 10)
@@ -369,35 +385,51 @@ SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection;
fid AsText(GeometryN(g, 2))
120 LINESTRING(0 0,10 10)
121 LINESTRING(3 6,7 9)
+122 NULL
+123 NULL
SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection;
fid AsText(GeometryN(g, 1))
120 POINT(0 0)
121 POINT(44 6)
+122 NULL
+123 NULL
explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point`
+Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,st_astext(st_geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point`
SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
first second w c o e d t i r
-120 120 1 1 0 1 0 0 1 0
+120 120 1 1 0 1 0 1 1 0
120 121 0 0 1 0 0 0 1 0
+120 122 0 1 NULL 0 NULL 0 NULL 0
+120 123 0 1 NULL 0 NULL 0 NULL 0
121 120 0 0 1 0 0 0 1 0
-121 121 1 1 0 1 0 0 1 0
+121 121 1 1 0 1 0 1 1 0
+121 122 0 1 NULL 0 NULL 0 NULL 0
+121 123 0 1 NULL 0 NULL 0 NULL 0
+122 120 1 0 NULL 0 NULL 0 NULL 0
+122 121 1 0 NULL 0 NULL 0 NULL 0
+122 122 1 1 NULL 1 NULL 0 NULL 0
+122 123 1 1 NULL 1 NULL 0 NULL 0
+123 120 1 0 NULL 0 NULL 0 NULL 0
+123 121 1 0 NULL 0 NULL 0 NULL 0
+123 122 1 1 NULL 1 NULL 0 NULL 0
+123 123 1 1 NULL 1 NULL 0 NULL 0
explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE g1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
-1 SIMPLE g2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
+1 SIMPLE g1 ALL NULL NULL NULL NULL 4 100.00 Using temporary; Using filesort
+1 SIMPLE g2 ALL NULL NULL NULL NULL 4 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid`
+Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,st_within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,st_contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,mbroverlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,st_equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,mbrdisjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,st_touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,mbrintersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,st_crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid`
DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
CREATE TABLE t1 (
gp point,
@@ -439,12 +471,12 @@ explain extended SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select astext(geometryfromwkb(aswkb(geometryfromtext('POINT(1 4)')))) AS `AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))))`
+Note 1003 select st_astext(st_geometryfromwkb(st_aswkb(st_geometryfromtext('POINT(1 4)')))) AS `AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))))`
explain extended SELECT AsText(GeometryFromWKB(AsWKB(PointFromText('POINT(1 4)'))));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select astext(geometryfromwkb(aswkb(geometryfromtext('POINT(1 4)')))) AS `AsText(GeometryFromWKB(AsWKB(PointFromText('POINT(1 4)'))))`
+Note 1003 select st_astext(st_geometryfromwkb(st_aswkb(st_geometryfromtext('POINT(1 4)')))) AS `AsText(GeometryFromWKB(AsWKB(PointFromText('POINT(1 4)'))))`
SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
SRID(GeomFromText('LineString(1 1,2 2)',101))
101
@@ -452,12 +484,12 @@ explain extended SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select srid(geometryfromtext('LineString(1 1,2 2)',101)) AS `SRID(GeomFromText('LineString(1 1,2 2)',101))`
+Note 1003 select srid(st_geometryfromtext('LineString(1 1,2 2)',101)) AS `SRID(GeomFromText('LineString(1 1,2 2)',101))`
explain extended select issimple(MultiPoint(Point(3, 6), Point(4, 10))), issimple(Point(3, 6));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select issimple(multipoint(point(3,6),point(4,10))) AS `issimple(MultiPoint(Point(3, 6), Point(4, 10)))`,issimple(point(3,6)) AS `issimple(Point(3, 6))`
+Note 1003 select st_issimple(st_multipoint(st_point(3,6),st_point(4,10))) AS `issimple(MultiPoint(Point(3, 6), Point(4, 10)))`,st_issimple(st_point(3,6)) AS `issimple(Point(3, 6))`
create table t1 (a geometry not null);
insert into t1 values (GeomFromText('Point(1 2)'));
insert into t1 values ('Garbage');
@@ -651,11 +683,11 @@ insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363
select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
t1 where object_id=85998;
object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
-85998 MULTIPOLYGON 0 POINT(115.31877315203187 -36.23747282102153)
+85998 MULTIPOLYGON 1 POINT(115.31877315203187 -36.23747282102153)
select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
t1 where object_id=85984;
object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
-85984 MULTIPOLYGON 0 POINT(-114.87787186923313 36.33101763469059)
+85984 MULTIPOLYGON 1 POINT(-114.87787186923313 36.33101763469059)
drop table t1;
create table t1 (fl geometry not null);
insert into t1 values (1);
@@ -802,17 +834,6 @@ create table t1 (g geometry not null);
insert into t1 values(default);
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
drop table t1;
-CREATE TABLE t1 (a GEOMETRY);
-CREATE VIEW v1 AS SELECT GeomFromwkb(ASBINARY(a)) FROM t1;
-CREATE VIEW v2 AS SELECT a FROM t1;
-DESCRIBE v1;
-Field Type Null Key Default Extra
-GeomFromwkb(ASBINARY(a)) geometry YES NULL
-DESCRIBE v2;
-Field Type Null Key Default Extra
-a geometry YES NULL
-DROP VIEW v1,v2;
-DROP TABLE t1;
create table t1 (name VARCHAR(100), square GEOMETRY);
INSERT INTO t1 VALUES("center", GeomFromText('POLYGON (( 0 0, 0 2, 2 2, 2 0, 0 0))'));
INSERT INTO t1 VALUES("small", GeomFromText('POLYGON (( 0 0, 0 1, 1 1, 1 0, 0 0))'));
@@ -846,7 +867,7 @@ mbroverlaps
down,left,right,up
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrtouches FROM t1 a1 JOIN t1 a2 ON MBRTouches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
mbrtouches
-down2,left2,right2,up2
+big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1 a2 ON MBRWithin( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
mbrwithin
big,center
@@ -867,7 +888,7 @@ overlaps
down,left,right,up
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS touches FROM t1 a1 JOIN t1 a2 ON Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
touches
-down2,left2,right2,up2
+big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS within FROM t1 a1 JOIN t1 a2 ON Within( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
within
big,center
@@ -1043,10 +1064,6 @@ create spatial index i on t1 (a);
ERROR 42000: A SPATIAL index may only contain a geometrical type column
drop table t1;
End of 5.1 tests
-CREATE TABLE t0 (a BINARY(32) NOT NULL);
-CREATE SPATIAL INDEX i on t0 (a);
-ERROR 42000: A SPATIAL index may only contain a geometrical type column
-INSERT INTO t0 VALUES (1);
CREATE TABLE t1(
col0 BINARY NOT NULL,
col2 TIMESTAMP,
@@ -1075,7 +1092,373 @@ col2 LINESTRING,
SPATIAL INDEX i1 (col1, col2)
);
ERROR HY000: Incorrect arguments to SPATIAL INDEX
-DROP TABLE t0, t1, t2;
+DROP TABLE t1;
+DROP TABLE t2;
+select ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))'));
+ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))'))
+1.5
+select ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))'));
+ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))'))
+160
+DROP DATABASE IF EXISTS gis_ogs;
+CREATE DATABASE gis_ogs;
+USE gis_ogs;
+#
+# C.3.3.1 Geometry types and functions schema construction
+#
+CREATE TABLE lakes (
+fid INTEGER NOT NULL PRIMARY KEY,
+name CHARACTER VARYING(64),
+shore POLYGON);
+CREATE TABLE road_segments (
+fid INTEGER NOT NULL PRIMARY KEY,
+name CHARACTER VARYING(64),
+aliases CHARACTER VARYING(64),
+num_lanes INTEGER,
+centerline LINESTRING);
+CREATE TABLE divided_routes (
+fid INTEGER NOT NULL PRIMARY KEY,
+name CHARACTER VARYING(64),
+num_lanes INTEGER,
+centerlines MULTILINESTRING);
+CREATE TABLE forests (
+fid INTEGER NOT NULL PRIMARY KEY,
+name CHARACTER VARYING(64),
+boundary MULTIPOLYGON);
+CREATE TABLE bridges (
+fid INTEGER NOT NULL PRIMARY KEY,
+name CHARACTER VARYING(64),
+position POINT);
+CREATE TABLE streams (
+fid INTEGER NOT NULL PRIMARY KEY,
+name CHARACTER VARYING(64),
+centerline LINESTRING);
+CREATE TABLE buildings (
+fid INTEGER NOT NULL PRIMARY KEY,
+address CHARACTER VARYING(64),
+position POINT,
+footprint POLYGON);
+CREATE TABLE ponds (
+fid INTEGER NOT NULL PRIMARY KEY,
+name CHARACTER VARYING(64),
+type CHARACTER VARYING(64),
+shores MULTIPOLYGON);
+CREATE TABLE named_places (
+fid INTEGER NOT NULL PRIMARY KEY,
+name CHARACTER VARYING(64),
+boundary POLYGON);
+CREATE TABLE map_neatlines (
+fid INTEGER NOT NULL PRIMARY KEY,
+neatline POLYGON);
+#
+# C.3.3.2 Geometry types and functions schema data loading
+#
+# Lakes
+INSERT INTO lakes VALUES (
+101, 'BLUE LAKE',
+PolyFromText(
+'POLYGON(
+(52 18,66 23,73 9,48 6,52 18),
+(59 18,67 18,67 13,59 13,59 18)
+)',
+101));
+# Road Segments
+INSERT INTO road_segments VALUES(102, 'Route 5', NULL, 2,
+LineFromText(
+'LINESTRING( 0 18, 10 21, 16 23, 28 26, 44 31 )' ,101));
+INSERT INTO road_segments VALUES(103, 'Route 5', 'Main Street', 4,
+LineFromText(
+'LINESTRING( 44 31, 56 34, 70 38 )' ,101));
+INSERT INTO road_segments VALUES(104, 'Route 5', NULL, 2,
+LineFromText(
+'LINESTRING( 70 38, 72 48 )' ,101));
+INSERT INTO road_segments VALUES(105, 'Main Street', NULL, 4,
+LineFromText(
+'LINESTRING( 70 38, 84 42 )' ,101));
+INSERT INTO road_segments VALUES(106, 'Dirt Road by Green Forest', NULL,
+1,
+LineFromText(
+'LINESTRING( 28 26, 28 0 )',101));
+# DividedRoutes
+INSERT INTO divided_routes VALUES(119, 'Route 75', 4,
+MLineFromText(
+'MULTILINESTRING((10 48,10 21,10 0),
+(16 0,16 23,16 48))', 101));
+# Forests
+INSERT INTO forests VALUES(109, 'Green Forest',
+MPolyFromText(
+'MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),
+(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))',
+101));
+# Bridges
+INSERT INTO bridges VALUES(110, 'Cam Bridge', PointFromText(
+'POINT( 44 31 )', 101));
+# Streams
+INSERT INTO streams VALUES(111, 'Cam Stream',
+LineFromText(
+'LINESTRING( 38 48, 44 41, 41 36, 44 31, 52 18 )', 101));
+INSERT INTO streams VALUES(112, NULL,
+LineFromText(
+'LINESTRING( 76 0, 78 4, 73 9 )', 101));
+# Buildings
+INSERT INTO buildings VALUES(113, '123 Main Street',
+PointFromText(
+'POINT( 52 30 )', 101),
+PolyFromText(
+'POLYGON( ( 50 31, 54 31, 54 29, 50 29, 50 31) )', 101));
+INSERT INTO buildings VALUES(114, '215 Main Street',
+PointFromText(
+'POINT( 64 33 )', 101),
+PolyFromText(
+'POLYGON( ( 66 34, 62 34, 62 32, 66 32, 66 34) )', 101));
+# Ponds
+INSERT INTO ponds VALUES(120, NULL, 'Stock Pond',
+MPolyFromText(
+'MULTIPOLYGON( ( ( 24 44, 22 42, 24 40, 24 44) ),
+( ( 26 44, 26 40, 28 42, 26 44) ) )', 101));
+# Named Places
+INSERT INTO named_places VALUES(117, 'Ashton',
+PolyFromText(
+'POLYGON( ( 62 48, 84 48, 84 30, 56 30, 56 34, 62 48) )', 101));
+INSERT INTO named_places VALUES(118, 'Goose Island',
+PolyFromText(
+'POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )', 101));
+# Map Neatlines
+INSERT INTO map_neatlines VALUES(115,
+PolyFromText(
+'POLYGON( ( 0 0, 0 48, 84 48, 84 0, 0 0 ) )', 101));
+#
+# C.3.3.3 Geometry types and functions schema test queries
+
+# Conformance Item T6
+SELECT Dimension(shore)
+FROM lakes
+WHERE name = 'Blue Lake';
+Dimension(shore)
+2
+# Conformance Item T7
+SELECT GeometryType(centerlines)
+FROM divided_routes
+WHERE name = 'Route 75';
+GeometryType(centerlines)
+MULTILINESTRING
+# Conformance Item T8
+SELECT AsText(boundary)
+FROM named_places
+WHERE name = 'Goose Island';
+AsText(boundary)
+POLYGON((67 13,67 18,59 18,59 13,67 13))
+# Conformance Item T9
+SELECT AsText(PolyFromWKB(AsBinary(boundary),101))
+FROM named_places
+WHERE name = 'Goose Island';
+AsText(PolyFromWKB(AsBinary(boundary),101))
+POLYGON((67 13,67 18,59 18,59 13,67 13))
+# Conformance Item T10
+SELECT SRID(boundary)
+FROM named_places
+WHERE name = 'Goose Island';
+SRID(boundary)
+101
+# Conformance Item T11
+SELECT IsEmpty(centerline)
+FROM road_segments
+WHERE name = 'Route 5'
+AND aliases = 'Main Street';
+IsEmpty(centerline)
+0
+# Conformance Item T14
+SELECT AsText(Envelope(boundary))
+FROM named_places
+WHERE name = 'Goose Island';
+AsText(Envelope(boundary))
+POLYGON((59 13,67 13,67 18,59 18,59 13))
+# Conformance Item T15
+SELECT X(position)
+FROM bridges
+WHERE name = 'Cam Bridge';
+X(position)
+44
+# Conformance Item T16
+SELECT Y(position)
+FROM bridges
+WHERE name = 'Cam Bridge';
+Y(position)
+31
+# Conformance Item T17
+SELECT AsText(StartPoint(centerline))
+FROM road_segments
+WHERE fid = 102;
+AsText(StartPoint(centerline))
+POINT(0 18)
+# Conformance Item T18
+SELECT AsText(EndPoint(centerline))
+FROM road_segments
+WHERE fid = 102;
+AsText(EndPoint(centerline))
+POINT(44 31)
+# Conformance Item T21
+SELECT GLength(centerline)
+FROM road_segments
+WHERE fid = 106;
+GLength(centerline)
+26
+# Conformance Item T22
+SELECT NumPoints(centerline)
+FROM road_segments
+WHERE fid = 102;
+NumPoints(centerline)
+5
+# Conformance Item T23
+SELECT AsText(PointN(centerline, 1))
+FROM road_segments
+WHERE fid = 102;
+AsText(PointN(centerline, 1))
+POINT(0 18)
+# Conformance Item T24
+SELECT AsText(Centroid(boundary))
+FROM named_places
+WHERE name = 'Goose Island';
+AsText(Centroid(boundary))
+POINT(63 15.5)
+# Conformance Item T26
+SELECT Area(boundary)
+FROM named_places
+WHERE name = 'Goose Island';
+Area(boundary)
+40
+# Conformance Item T27
+SELECT AsText(ExteriorRing(shore))
+FROM lakes
+WHERE name = 'Blue Lake';
+AsText(ExteriorRing(shore))
+LINESTRING(52 18,66 23,73 9,48 6,52 18)
+# Conformance Item T28
+SELECT NumInteriorRings(shore)
+FROM lakes
+WHERE name = 'Blue Lake';
+NumInteriorRings(shore)
+1
+# Conformance Item T29
+SELECT AsText(InteriorRingN(shore, 1))
+FROM lakes
+WHERE name = 'Blue Lake';
+AsText(InteriorRingN(shore, 1))
+LINESTRING(59 18,67 18,67 13,59 13,59 18)
+# Conformance Item T30
+SELECT NumGeometries(centerlines)
+FROM divided_routes
+WHERE name = 'Route 75';
+NumGeometries(centerlines)
+2
+# Conformance Item T31
+SELECT AsText(GeometryN(centerlines, 2))
+FROM divided_routes
+WHERE name = 'Route 75';
+AsText(GeometryN(centerlines, 2))
+LINESTRING(16 0,16 23,16 48)
+# Conformance Item T32
+SELECT IsClosed(centerlines)
+FROM divided_routes
+WHERE name = 'Route 75';
+IsClosed(centerlines)
+0
+# Conformance Item T33
+SELECT GLength(centerlines)
+FROM divided_routes
+WHERE name = 'Route 75';
+GLength(centerlines)
+96
+# Conformance Item T34
+SELECT AsText(Centroid(shores))
+FROM ponds
+WHERE fid = 120;
+AsText(Centroid(shores))
+POINT(25 42)
+# Conformance Item T36
+SELECT Area(shores)
+FROM ponds
+WHERE fid = 120;
+Area(shores)
+8
+# Conformance Item T37
+SELECT ST_Equals(boundary,
+PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1))
+FROM named_places
+WHERE name = 'Goose Island';
+ST_Equals(boundary,
+PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1))
+1
+# Conformance Item T38
+SELECT ST_Disjoint(centerlines, boundary)
+FROM divided_routes, named_places
+WHERE divided_routes.name = 'Route 75'
+AND named_places.name = 'Ashton';
+ST_Disjoint(centerlines, boundary)
+1
+# Conformance Item T39
+SELECT ST_Touches(centerline, shore)
+FROM streams, lakes
+WHERE streams.name = 'Cam Stream'
+AND lakes.name = 'Blue Lake';
+ST_Touches(centerline, shore)
+1
+# Conformance Item T42
+SELECT Crosses(road_segments.centerline, divided_routes.centerlines)
+FROM road_segments, divided_routes
+WHERE road_segments.fid = 102
+AND divided_routes.name = 'Route 75';
+Crosses(road_segments.centerline, divided_routes.centerlines)
+1
+# Conformance Item T43
+SELECT ST_Intersects(road_segments.centerline, divided_routes.centerlines)
+FROM road_segments, divided_routes
+WHERE road_segments.fid = 102
+AND divided_routes.name = 'Route 75';
+ST_Intersects(road_segments.centerline, divided_routes.centerlines)
+1
+# Conformance Item T44
+SELECT ST_Contains(forests.boundary, named_places.boundary)
+FROM forests, named_places
+WHERE forests.name = 'Green Forest'
+AND named_places.name = 'Ashton';
+ST_Contains(forests.boundary, named_places.boundary)
+0
+# Conformance Item T46
+SELECT ST_Distance(position, boundary)
+FROM bridges, named_places
+WHERE bridges.name = 'Cam Bridge'
+AND named_places.name = 'Ashton';
+ST_Distance(position, boundary)
+12
+# Conformance Item T48
+SELECT AsText(ST_Difference(named_places.boundary, forests.boundary))
+FROM named_places, forests
+WHERE named_places.name = 'Ashton'
+AND forests.name = 'Green Forest';
+AsText(ST_Difference(named_places.boundary, forests.boundary))
+POLYGON((56 34,62 48,84 48,84 42,56 34))
+SELECT AsText(ST_Union(shore, boundary))
+FROM lakes, named_places
+WHERE lakes.name = 'Blue Lake'
+AND named_places.name = 'Goose Island';
+AsText(ST_Union(shore, boundary))
+POLYGON((48 6,52 18,66 23,73 9,48 6))
+# Conformance Item T50
+SELECT AsText(ST_SymDifference(shore, boundary))
+FROM lakes, named_places
+WHERE lakes.name = 'Blue Lake'
+AND named_places.name = 'Ashton';
+AsText(ST_SymDifference(shore, boundary))
+MULTIPOLYGON(((48 6,52 18,66 23,73 9,48 6),(59 13,59 18,67 18,67 13,59 13)),((56 30,56 34,62 48,84 48,84 30,56 30)))
+# Conformance Item T51
+SELECT count(*)
+FROM buildings, bridges
+WHERE ST_Contains(ST_Buffer(bridges.position, 15.0), buildings.footprint) = 1;
+count(*)
+1
+DROP DATABASE gis_ogs;
+USE test;
#
# Bug#11908153: CRASH AND/OR VALGRIND ERRORS IN FIELD_BLOB::GET_KEY_IMAGE
#
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 7b22b450b62..4ac1a298ffe 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1544,7 +1544,8 @@ EXPLAIN SELECT 1 FROM t1 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index PRIMARY,i2 PRIMARY 4 NULL 144 Using index
-1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Using where; FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 144
CREATE TABLE t2 (a INT, b INT, KEY(a));
INSERT INTO t2 VALUES (1, 1), (2, 2), (3,3), (4,4);
EXPLAIN SELECT a, SUM(b) FROM t2 GROUP BY a LIMIT 2;
@@ -1894,8 +1895,8 @@ SELECT a, AVG(t1.b),
FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL a 10 NULL 9 Using index
-3 DEPENDENT SUBQUERY t12 ref a a 10 func,func 2 Using where
-2 DEPENDENT SUBQUERY t11 ref a a 10 func,func 2 Using where
+3 DEPENDENT SUBQUERY t12 ref a a 10 func,func 2 Using index condition
+2 DEPENDENT SUBQUERY t11 ref a a 10 func,func 2 Using index condition
SELECT a, AVG(t1.b),
(SELECT t11.c FROM t1 t11 WHERE t11.a = t1.a AND t11.b = AVG(t1.b)) AS t11c,
(SELECT t12.c FROM t1 t12 WHERE t12.a = t1.a AND t12.b = AVG(t1.b)) AS t12c
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index 047ae5e1307..f3457c43e00 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -2401,8 +2401,9 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index NULL a 10 NULL 15 Using where; Using index
-2 DEPENDENT SUBQUERY t1 index NULL a 10 NULL 1 Using index
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 8 Using where
+1 PRIMARY t1_outer ref a a 5 <subquery2>.max(b) 2 Using index
+2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/mysql-test/r/index_intersect.result b/mysql-test/r/index_intersect.result
index 3c3c892851e..e22b16fcd91 100644
--- a/mysql-test/r/index_intersect.result
+++ b/mysql-test/r/index_intersect.result
@@ -74,12 +74,12 @@ EXPLAIN
SELECT * FROM City
WHERE Name LIKE 'M%' AND Population > 300000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Name Name 35 NULL # Using where
+1 SIMPLE City range Population,Name Name 35 NULL # Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE Name LIKE 'M%' AND Population > 7000000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Name Population 4 NULL # Using where
+1 SIMPLE City range Population,Name Population 4 NULL # Using index condition; Using where
SELECT * FROM City USE INDEX ()
WHERE Name LIKE 'C%' AND Population > 1000000;
ID Name Country Population
@@ -371,7 +371,7 @@ EXPLAIN
SELECT * FROM City
WHERE Name BETWEEN 'G' AND 'K' AND Population > 500000 AND Country LIKE 'C%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Name,Country Name # NULL # Using where
+1 SIMPLE City range Population,Name,Country Name # NULL # Using index condition; Using where
SELECT * FROM City USE INDEX ()
WHERE Name BETWEEN 'M' AND 'N' AND Population > 1000000 AND Country LIKE 'C%';
ID Name Country Population
@@ -462,7 +462,7 @@ EXPLAIN
SELECT * FROM City
WHERE ID BETWEEN 501 AND 1000 AND Population > 700000 AND Country LIKE 'C%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country Population 4 NULL # Using where
+1 SIMPLE City range PRIMARY,Population,Country Population 4 NULL # Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE ID BETWEEN 1 AND 500 AND Population > 1000000 AND Country LIKE 'A%';
@@ -472,7 +472,7 @@ EXPLAIN
SELECT * FROM City
WHERE ID BETWEEN 2001 AND 2500 AND Population > 300000 AND Country LIKE 'H%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country Country 3 NULL # Using where
+1 SIMPLE City range PRIMARY,Population,Country Country 3 NULL # Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE ID BETWEEN 3701 AND 4000 AND Population > 1000000
@@ -484,7 +484,7 @@ SELECT * FROM City
WHERE ID BETWEEN 3001 AND 4000 AND Population > 600000
AND Country BETWEEN 'S' AND 'Z' ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country Population 4 NULL # Using where
+1 SIMPLE City range PRIMARY,Population,Country Population 4 NULL # Using index condition; Using where
SELECT * FROM City USE INDEX ()
WHERE ID BETWEEN 501 AND 1000 AND Population > 700000 AND Country LIKE 'C%';
ID Name Country Population
@@ -733,7 +733,7 @@ EXPLAIN
SELECT * FROM City
WHERE Name BETWEEN 'G' AND 'J' AND Population > 500000 AND Country LIKE 'C%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Country,Name Name 35 NULL # Using where
+1 SIMPLE City range Population,Country,Name Name 35 NULL # Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE ID BETWEEN 1 AND 500 AND Population > 1000000 AND Country LIKE 'A%';
@@ -744,7 +744,7 @@ SELECT * FROM City
WHERE ID BETWEEN 3001 AND 4000 AND Population > 600000
AND Country BETWEEN 'S' AND 'Z';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country Population 4 NULL # Using where
+1 SIMPLE City range PRIMARY,Population,Country Population 4 NULL # Using index condition; Using where
SELECT * FROM City WHERE
Name LIKE 'C%' AND Population > 1000000;
ID Name Country Population
@@ -1035,7 +1035,7 @@ EXPLAIN
SELECT * FROM t1
WHERE (f1 < 535 OR f1 > 985) AND ( f4='r' OR f4 LIKE 'a%' ) ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,f4 f4 35 NULL # Using where
+1 SIMPLE t1 range PRIMARY,f4 f4 35 NULL # Using index condition; Using where
SELECT * FROM t1
WHERE (f1 < 535 OR f1 > 985) AND ( f4='r' OR f4 LIKE 'a%' ) ;
f1 f4 f5
diff --git a/mysql-test/r/index_merge_innodb.result b/mysql-test/r/index_merge_innodb.result
index 363da1c8ecf..e698d31e1ea 100644
--- a/mysql-test/r/index_merge_innodb.result
+++ b/mysql-test/r/index_merge_innodb.result
@@ -549,7 +549,7 @@ primary key (pk1, pk2)
);
explain select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,key1 PRIMARY 8 NULL 9 Using where
+1 SIMPLE t1 range PRIMARY,key1 PRIMARY 8 NULL 9 Using index condition; Using where
select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
pk1 pk2 key1 key2 pktail1ok pktail2ok pktail3bad pktail4bad pktail5bad pk2copy badkey filler1 filler2
1 10 0 0 0 0 0 0 0 10 0 filler-data-10 filler2
diff --git a/mysql-test/r/index_merge_myisam.result b/mysql-test/r/index_merge_myisam.result
index 00c924988da..8953682ddb7 100644
--- a/mysql-test/r/index_merge_myisam.result
+++ b/mysql-test/r/index_merge_myisam.result
@@ -21,7 +21,7 @@ Table Op Msg_type Msg_text
test.t0 analyze status OK
explain select * from t0 where key1 < 3 or key1 > 1020;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t0 range i1 i1 4 NULL 78 Using where
+1 SIMPLE t0 range i1 i1 4 NULL 78 Using index condition; Using where
explain
select * from t0 where key1 < 3 or key2 > 1020;
id select_type table type possible_keys key key_len ref rows Extra
@@ -277,7 +277,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain select * from t0,t1 where t0.key1 < 3 and
(t1.key1 = t0.key1 or t1.key8 = t0.key1);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t0 range i1 i1 4 NULL 3 Using where
+1 SIMPLE t0 range i1 i1 4 NULL 3 Using index condition
1 SIMPLE t1 ALL i1,i8 NULL NULL NULL 1024 Range checked for each record (index map: 0x81)
explain select * from t1 where key1=3 or key2=4
union select * from t1 where key1<4 or key3=5;
@@ -1379,7 +1379,7 @@ primary key (pk1, pk2)
);
explain select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,key1 PRIMARY 8 NULL 7 Using where
+1 SIMPLE t1 range PRIMARY,key1 PRIMARY 8 NULL 7 Using index condition; Using where
select * from t1 where pk1 = 1 and pk2 < 80 and key1=0;
pk1 pk2 key1 key2 pktail1ok pktail2ok pktail3bad pktail4bad pktail5bad pk2copy badkey filler1 filler2
1 10 0 0 0 0 0 0 0 10 0 filler-data-10 filler2
diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result
index 0f7f2411c0c..c7d78cff88c 100644
--- a/mysql-test/r/join.result
+++ b/mysql-test/r/join.result
@@ -1266,7 +1266,7 @@ Variable_name Value
Handler_read_first 0
Handler_read_key 1
Handler_read_last 0
-Handler_read_next 2
+Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 1
diff --git a/mysql-test/r/join_nested.result b/mysql-test/r/join_nested.result
index 234ac4a88d9..fb4ebb3c4b7 100644
--- a/mysql-test/r/join_nested.result
+++ b/mysql-test/r/join_nested.result
@@ -1457,12 +1457,12 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL X
1 SIMPLE t3 ref a a 5 test.t2.b X Using where
1 SIMPLE t5 ref a a 5 test.t3.b X
-1 SIMPLE t4 ref a a 5 test.t3.b X Using where
+1 SIMPLE t4 ref a a 5 test.t3.b X Using index condition
explain select * from (t4 join t6 on t6.a=t4.b) right join t3 on t4.a=t3.b
join t2 left join (t5 join t7 on t7.a=t5.b) on t5.a=t2.b where t3.a<=>t2.b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL X
-1 SIMPLE t3 ref a a 5 test.t2.b X Using where
+1 SIMPLE t3 ref a a 5 test.t2.b X Using index condition
1 SIMPLE t4 ref a a 5 test.t3.b X Using where
1 SIMPLE t6 ref a a 5 test.t4.b X
1 SIMPLE t5 ref a a 5 test.t2.b X Using where
diff --git a/mysql-test/r/join_optimizer.result b/mysql-test/r/join_optimizer.result
index 5411b046766..ad7267ab665 100644
--- a/mysql-test/r/join_optimizer.result
+++ b/mysql-test/r/join_optimizer.result
@@ -33,5 +33,5 @@ SELECT STRAIGHT_JOIN g.id FROM t2 a, t3 g USE INDEX(groups_dt)
WHERE g.domain = 'queue' AND g.type = a.type;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a ALL NULL NULL NULL NULL 2 Using where
-1 SIMPLE g ref groups_dt groups_dt 70 const,test.a.type 13 Using where
+1 SIMPLE g ref groups_dt groups_dt 70 const,test.a.type 13 Using index condition
drop table t0,t1,t2,t3;
diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
index 5b4395dcc29..41c7ecee220 100644
--- a/mysql-test/r/key_cache.result
+++ b/mysql-test/r/key_cache.result
@@ -646,7 +646,7 @@ select p from t1 where p between 1010 and 1020;
p
explain select i from t2 where p between 1010 and 1020;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 28 Using where
+1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 28 Using index condition
select i from t2 where p between 1010 and 1020;
i
1
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index 622640a897c..b5c85555ed8 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -677,7 +677,7 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,files PRIMARY 35 NULL 5 Using where
+1 SIMPLE t1 range PRIMARY,files PRIMARY 35 NULL 5 Using index condition
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/mysql-test/r/mix2_myisam.result b/mysql-test/r/mix2_myisam.result
index cfa721c1dcb..e5f5857d2c9 100644
--- a/mysql-test/r/mix2_myisam.result
+++ b/mysql-test/r/mix2_myisam.result
@@ -1114,11 +1114,11 @@ count(*)
29267
explain select * from t1 where c between 1 and 2500;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c c 5 NULL # Using where
+1 SIMPLE t1 range c c 5 NULL # Using index condition
update t1 set c=a;
explain select * from t1 where c between 1 and 2500;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c c 5 NULL # Using where
+1 SIMPLE t1 range c c 5 NULL # Using index condition
drop table t1,t2;
create table t1 (id int primary key auto_increment, fk int, index index_fk (fk)) engine=MyISAM;
insert into t1 (id) values (null),(null),(null),(null),(null);
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index ad714fdb91b..c96f7bb4e51 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -392,7 +392,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a NULL NULL NULL 5 Using where
explain select * from t1 force index (a) where a=0 or a=2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 4 NULL 4 Using where
+1 SIMPLE t1 range a a 4 NULL 4 Using index condition; Using where
explain select * from t1 where c=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c,c_2 c 5 const 1
diff --git a/mysql-test/r/myisam_icp.result b/mysql-test/r/myisam_icp.result
index 0426e1bdfba..d855c9d439b 100644
--- a/mysql-test/r/myisam_icp.result
+++ b/mysql-test/r/myisam_icp.result
@@ -763,8 +763,8 @@ t2.b NOT IN (SELECT t4.b FROM t3 STRAIGHT_JOIN t4 WHERE t4.b <= 2 AND t4.c = t3.
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2
-2 DEPENDENT SUBQUERY t4 ref_or_null b b 5 func 2 Using where; Full scan on NULL key
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 2
+2 SUBQUERY t4 range b b 5 NULL 1 Using index condition; Using where; Rowid-ordered scan; Using join buffer (flat, BNL join)
SELECT * FROM t1 LEFT JOIN t2 ON t1.c=t2.b
WHERE
t2.b NOT IN (SELECT t4.b FROM t3 STRAIGHT_JOIN t4 WHERE t4.b <= 2 AND t4.c = t3.c);
diff --git a/mysql-test/r/mysqld--help-notwin.result b/mysql-test/r/mysqld--help-notwin.result
index acdee8d8e89..e0515639a3b 100644
--- a/mysql-test/r/mysqld--help-notwin.result
+++ b/mysql-test/r/mysqld--help-notwin.result
@@ -1000,7 +1000,7 @@ old-passwords FALSE
old-style-user-limits FALSE
optimizer-prune-level 1
optimizer-search-depth 62
-optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
performance-schema FALSE
performance-schema-events-waits-history-long-size 10000
performance-schema-events-waits-history-size 10
diff --git a/mysql-test/r/mysqld--help-win.result b/mysql-test/r/mysqld--help-win.result
index 361d30620f7..10a48dbce70 100644
--- a/mysql-test/r/mysqld--help-win.result
+++ b/mysql-test/r/mysqld--help-win.result
@@ -32,11 +32,18 @@ The following options may be given as the first argument:
--big-tables Allow big result sets by saving all temporary sets on
file (Solves most 'table full' errors)
--bind-address=name IP address to bind to.
+ --binlog-annotate-row-events
+ Tells the master to annotate RBR events with the
+ statement that caused these events
--binlog-cache-size=#
The size of the transactional cache for updates to
transactional engines for the binary log. If you often
use transactions containing many statements, you can
increase this to get more performance
+ --binlog-checksum=name
+ Type of BINLOG_CHECKSUM_ALG. Include checksum for log
+ events in the binary log. Possible values are NONE and
+ CRC32; default is NONE.
--binlog-direct-non-transactional-updates
Causes updates to non-transactional engines using
statement format to be written directly to binary log.
@@ -63,6 +70,15 @@ The following options may be given as the first argument:
--binlog-ignore-db=name
Tells the master that updates to the given database
should not be logged to the binary log.
+ --binlog-optimize-thread-scheduling
+ Run fast part of group commit in a single thread, to
+ optimize kernel thread scheduling. On by default. Disable
+ to run each transaction in group commit in its own
+ thread, which can be slower at very high concurrency.
+ This option is mostly for testing one algorithm versus
+ the other, and it should not normally be necessary to
+ change it.
+ (Defaults to on; use --skip-binlog-optimize-thread-scheduling to disable.)
--binlog-row-event-max-size=#
The maximum size of a row-based binary log event in
bytes. Rows will be grouped into events smaller than this
@@ -104,6 +120,16 @@ The following options may be given as the first argument:
--date-format=name The DATE format (ignored)
--datetime-format=name
The DATETIME format (ignored)
+ --deadlock-search-depth-long=#
+ Long search depth for the two-step deadlock detection
+ --deadlock-search-depth-short=#
+ Short search depth for the two-step deadlock detection
+ --deadlock-timeout-long=#
+ Long timeout for the two-step deadlock detection (in
+ microseconds)
+ --deadlock-timeout-short=#
+ Short timeout for the two-step deadlock detection (in
+ microseconds)
--default-storage-engine=name
The default storage engine for new tables
--default-time-zone=name
@@ -148,6 +174,11 @@ The following options may be given as the first argument:
With this option enabled you can run myisamchk to test
(not repair) tables while the MySQL server is running.
Disable with --skip-external-locking.
+ --extra-max-connections=#
+ The number of connections on extra-port
+ --extra-port=# Extra port number to use for tcp connections in a
+ one-thread-per-connection manner. 0 means don't use
+ another port
--flush Flush MyISAM tables to disk between SQL commands
--flush-time=# A dedicated thread is created to flush all tables at the
given interval
@@ -177,6 +208,7 @@ The following options may be given as the first argument:
--ignore-builtin-innodb
Disable initialization of builtin InnoDB plugin
--init-connect=name Command(s) that are executed for each new connection
+ (unless the user has SUPER privilege)
--init-file=name Read SQL commands from this file at startup
--init-rpl-role=name
Set the replication role.
@@ -186,7 +218,14 @@ The following options may be given as the first argument:
The number of seconds the server waits for activity on an
interactive connection before closing it
--join-buffer-size=#
- The size of the buffer that is used for full joins
+ The size of the buffer that is used for joins
+ --join-buffer-space-limit=#
+ The limit of the space for all join buffers used by a
+ query
+ --join-cache-level=#
+ Controls what join operations can be executed with join
+ buffers. Odd numbers are used for plain join buffers
+ while even numbers are used for linked buffers
--keep-files-on-create
Don't overwrite stale .MYD and .MYI even if no directory
is specified
@@ -204,6 +243,8 @@ The following options may be given as the first argument:
The default size of key cache blocks
--key-cache-division-limit=#
The minimum percentage of warm blocks in key cache
+ --key-cache-segments=#
+ The number of segments in a key cache
-L, --language=name Client error messages in given language. May be given as
a full path. Deprecated. Use --lc-messages-dir instead.
--lc-messages=name Set the language used for the error messages.
@@ -219,10 +260,20 @@ The following options may be given as the first argument:
error.
-l, --log[=name] Log connections and queries to file (deprecated option,
use --general-log/--general-log-file instead).
- --log-bin[=name] Log update queries in binary format. Optional (but
- strongly recommended to avoid replication problems if
- server's hostname changes) argument should be the chosen
- location for the binary log files.
+ --log-basename=name Basename for all log files and the .pid file. This sets
+ all log file names at once (in 'datadir') and is normally
+ the only option you need for specifying log files. Sets
+ names for --log-bin, --log-bin-index, --relay-log,
+ --relay-log-index, --general-log-file,
+ --log-slow-query-log-file, --log-error-file, and
+ --pid-file
+ --log-bin[=name] Log update queries in binary format. Optional argument
+ should be name for binary log. If not given
+ datadir/'log-basename'-bin or 'datadir'/mysql-bin will be
+ used (the later if --log-basename is not specified). We
+ strongly recommend to use either --log-basename or
+ specify a filename to ensure that replication doesn't
+ stop if the real hostname of the computer changes'.
--log-bin-index=name
File that holds the names for last binary log files.
--log-bin-trust-function-creators
@@ -234,7 +285,9 @@ The following options may be given as the first argument:
ALWAYS use row-based binary logging, the security issues
do not exist and the binary logging cannot break, so you
can safely set this to TRUE
- --log-error[=name] Error log file
+ --log-error[=name] Log errors to file (instead of stdout). If file name is
+ not specified then 'datadir'/'log-basename'.err or the
+ pid-file path with extension .err is used
--log-isam[=name] Log all MyISAM changes to file.
--log-output=name Syntax: log-output=value[,value...], where "value" could
be TABLE, FILE or NONE
@@ -249,21 +302,38 @@ The following options may be given as the first argument:
--log-slow-admin-statements
Log slow OPTIMIZE, ANALYZE, ALTER and other
administrative statements to the slow log if it is open.
+ --log-slow-filter=name
+ Log only certain types of queries. Multiple flags can be
+ specified, separated by commas. Valid values are admin,
+ slave, filesort, filesort_on_disk, full_join, full_scan,
+ query_cache, query_cache_miss, tmp_table,
+ tmp_table_on_disk
--log-slow-queries[=name]
- Log slow queries to a table or log file. Defaults logging
- to table mysql.slow_log or hostname-slow.log if
- --log-output=file is used. Must be enabled to activate
- other slow log options. Deprecated option, use
+ Enable logging of slow queries (longer than
+ --long-query-time) to log file or table. Optional
+ argument is a file name for the slow log. If not given,
+ 'log-basename'-slow.log will be used. Use
+ --log-output=TABLE if you want to have the log in the
+ table 'mysql.slow_log'. Deprecated option, use
--slow-query-log/--slow-query-log-file instead.
+ --log-slow-rate-limit=#
+ Write to slow log every #th slow query. Set to 1 to log
+ everything. Increase it to reduce the size of the slow or
+ the performance impact of slow logging
--log-slow-slave-statements
Log slow statements executed by slave thread to the slow
log if it is open.
+ --log-slow-verbosity=name
+ log-slow-verbosity=[value[,value ...]] where value is one
+ of 'innodb', 'query_plan'
--log-tc=name Path to transaction coordinator log (used for
transactions that affect more than one storage engine,
when binary log is disabled).
--log-tc-size=# Size of transaction coordinator log.
-W, --log-warnings[=#]
- Log some not critical warnings to the log file
+ Log some not critical warnings to the general log
+ file.Value can be between 0 and 11. Higher values mean
+ more verbosity
--long-query-time=# Log all queries that have taken more than long_query_time
seconds to execute to file. The argument will be treated
as a decimal value with microsecond precision
@@ -276,10 +346,14 @@ The following options may be given as the first argument:
--master-info-file=name
The location and name of the file that remembers the
master and where the I/O replication thread is in the
- master's binlogs.
+ master's binlogs. Defaults to master.info
--master-retry-count=#
The number of tries the slave will make to connect to the
master before giving up.
+ --master-verify-checksum
+ Force checksum verification of logged events in the
+ binary log before sending them to slaves or printing them
+ in the output of SHOW BINLOG EVENTS
--max-allowed-packet=#
Max packet length to send to or receive from the server
--max-binlog-cache-size=#
@@ -338,8 +412,9 @@ The following options may be given as the first argument:
--min-examined-row-limit=#
Don't write queries to slow log that examine fewer rows
than that
+ --mrr-buffer-size=# Size of buffer to use when using MRR with range access
--multi-range-count=#
- Number of key ranges to request at once
+ Ignored. Use mrr_buffer_size instead
--myisam-block-size=#
Block size to be used for MyISAM index pages
--myisam-data-pointer-size=#
@@ -352,7 +427,8 @@ The following options may be given as the first argument:
MySQL tables
--myisam-recover-options[=name]
Syntax: myisam-recover-options[=option[,option...]],
- where option can be DEFAULT, BACKUP, FORCE, QUICK, or OFF
+ where option can be DEFAULT, BACKUP, BACKUP_ALL, FORCE,
+ QUICK, or OFF
--myisam-repair-threads=#
If larger than 1, when repairing a MyISAM table all
indexes will be created in parallel, with one thread per
@@ -378,7 +454,6 @@ The following options may be given as the first argument:
--net-write-timeout=#
Number of seconds to wait for a block to be written to a
connection before aborting the write
- -n, --new Use very new possible "unsafe" functions
--old Use compatible behavior
--old-alter-table Use old, non-optimized alter table
--old-passwords Use old password encryption method (needed for 4.0 and
@@ -414,10 +489,18 @@ The following options may be given as the first argument:
deprecated
--optimizer-switch=name
optimizer_switch=option=val[,option=val...], where option
- is one of {index_merge, index_merge_union,
- index_merge_sort_union, index_merge_intersection,
- engine_condition_pushdown} and val is one of {on, off,
- default}
+ is one of {derived_merge, derived_with_keys, firstmatch,
+ in_to_exists, engine_condition_pushdown,
+ index_condition_pushdown, index_merge,
+ index_merge_intersection, index_merge_sort_intersection,
+ index_merge_sort_union, index_merge_union,
+ join_cache_bka, join_cache_hashed,
+ join_cache_incremental, loosescan, materialization, mrr,
+ mrr_cost_based, mrr_sort_keys, optimize_join_buffer_size,
+ outer_join_with_cache, partial_match_rowid_merge,
+ partial_match_table_scan, semijoin, semijoin_with_cache,
+ subquery_cache, table_elimination } and val is one of
+ {on, off, default}
--performance-schema
Enable the performance schema.
--performance-schema-events-waits-history-long-size=#
@@ -456,6 +539,10 @@ The following options may be given as the first argument:
where each plugin is identified as name=library, where
name is the plugin name and library is the plugin library
in plugin_dir.
+ --plugin-maturity=name
+ The lowest desirable plugin maturity (unknown,
+ experimental, alpha, beta, gamma, or stable). Plugins
+ less mature than that will not be installed or loaded.
-P, --port=# Port number to use for connection or 0 to default to,
my.cnf, $MYSQL_TCP_PORT, /etc/services, built-in default
(3306), whatever comes first
@@ -467,6 +554,10 @@ The following options may be given as the first argument:
indexes
--profiling-history-size=#
Limit of query profiling memory
+ --progress-report-time=#
+ Seconds between sending progress reports to the client
+ for time-consuming statements. Set to 0 to disable
+ progress reporting.
--query-alloc-block-size=#
Allocation block size for query parsing and execution
--query-cache-limit=#
@@ -475,6 +566,9 @@ The following options may be given as the first argument:
The minimum size for blocks allocated by the query cache
--query-cache-size=#
The memory allocated to store results from old queries
+ --query-cache-strip-comments
+ Strip all comments from a query before storing it in the
+ query cache
--query-cache-type=name
OFF = Don't cache or retrieve results. ON = Cache all
results except SELECT SQL_NO_CACHE ... queries. DEMAND =
@@ -514,6 +608,10 @@ The following options may be given as the first argument:
transaction processed
--relay-log-space-limit=#
Maximum space to use for all relay logs
+ --replicate-annotate-row-events
+ Tells the slave to write annotate rows events recieved
+ from the master to its own binary log. Ignored if
+ log_slave_updates is not set
--replicate-do-db=name
Tells the slave thread to restrict replication to the
specified database. To specify more than one database,
@@ -590,6 +688,9 @@ The following options may be given as the first argument:
not sure, leave this option unset
--report-user=name The account user name of the slave to be reported to the
master during slave registration
+ --rowid-merge-buff-size=#
+ The size of the buffers used [NOT] IN evaluation via
+ partial matching
--rpl-recovery-rank=#
Unused, will be removed
--safe-mode Skip some optimize stages (for testing).
@@ -608,17 +709,17 @@ The following options may be given as the first argument:
--show-slave-auth-info
Show user and password in SHOW SLAVE HOSTS on this
master.
+ --skip-bdb Deprecated option; Exist only for compatiblity with old
+ my.cnf files
--skip-grant-tables Start without grant tables. This gives all users FULL
ACCESS to all tables.
--skip-host-cache Don't cache host names.
--skip-name-resolve Don't resolve hostnames. All hostnames are IP's or
'localhost'.
--skip-networking Don't allow connection with TCP/IP
- --skip-new Don't use new, possibly wrong routines.
--skip-show-database
Don't allow 'SHOW DATABASE' commands
--skip-slave-start If set, slave is not autostarted.
- --skip-stack-trace Don't print a stack trace on failure.
--skip-thread-priority
Don't give threads different priorities. This option is
deprecated because it has no effect; the implied behavior
@@ -641,6 +742,12 @@ The following options may be given as the first argument:
--slave-skip-errors=name
Tells the slave thread to continue replication when a
query event returns an error from the provided list
+ --slave-sql-verify-checksum
+ Force checksum verification of replication events after
+ reading them from relay log. Note: Events are always
+ checksum-verified by slave on receiving them from the
+ network before writing them to the relay log
+ (Defaults to on; use --skip-slave-sql-verify-checksum to disable.)
--slave-transaction-retries=#
Number of times the slave SQL thread will retry a
transaction in case it failed with a deadlock or elapsed
@@ -672,6 +779,8 @@ The following options may be given as the first argument:
replication.
--sql-mode=name Syntax: sql-mode=mode[,mode[,mode...]]. See the manual
for the complete list of valid sql modes
+ --stack-trace Print a symbolic stack trace on failure
+ (Defaults to on; use --skip-stack-trace to disable.)
--standalone Dummy option to start as a standalone program (NT).
-s, --symbolic-links
Enable symbolic link support.
@@ -688,6 +797,9 @@ The following options may be given as the first argument:
Synchronously flush relay log info to disk after every
#th transaction. Use 0 (default) to disable synchronous
flushing
+ --sync-sys Enable system sync calls. Disable only when running tests
+ or debugging!
+ (Defaults to on; use --skip-sync-sys to disable.)
--sysdate-is-now Non-default option to alias SYSDATE() to NOW() to make it
safe-replicable. Since 5.0, SYSDATE() returns a `dynamic'
value different for different invocations, even within
@@ -700,18 +812,21 @@ The following options may be given as the first argument:
--tc-heuristic-recover=name
Decision to use in heuristic recover process. Possible
values are COMMIT or ROLLBACK.
+ --thread-alarm Enable system thread alarm calls. Disabling it may be
+ useful in debugging or testing, never do it in production
+ (Defaults to on; use --skip-thread-alarm to disable.)
--thread-cache-size=#
How many threads we should keep in a cache for reuse
--thread-handling=name
Define threads usage for handling queries, one of
- one-thread-per-connection, no-threads, loaded-dynamically
+ one-thread-per-connection, no-threads
--thread-stack=# The stack size for each thread
--time-format=name The TIME format (ignored)
--timed-mutexes Specify whether to time mutexes (only InnoDB mutexes are
currently supported)
--tmp-table-size=# If an internal in-memory temporary table exceeds this
size, MySQL will automatically convert it to an on-disk
- MyISAM table
+ MyISAM or Aria table
-t, --tmpdir=name Path for temporary files. Several paths may be specified,
separated by a semicolon (;), in this case they are used
in a round-robin fashion
@@ -731,6 +846,9 @@ The following options may be given as the first argument:
of the underlying table and the query uses a LIMIT clause
(usually get from GUI tools)
-u, --user=name Run mysqld daemon as user.
+ --userstat Enables statistics gathering for USER_STATISTICS,
+ CLIENT_STATISTICS, INDEX_STATISTICS and TABLE_STATISTICS
+ tables in the INFORMATION_SCHEMA
-v, --verbose Used with --help option for detailed help.
-V, --version Output version information and exit.
--wait-timeout=# The number of seconds the server waits for activity on a
@@ -746,9 +864,12 @@ automatic-sp-privileges TRUE
back-log 50
big-tables FALSE
bind-address (No default value)
+binlog-annotate-row-events FALSE
binlog-cache-size 32768
+binlog-checksum NONE
binlog-direct-non-transactional-updates FALSE
binlog-format STATEMENT
+binlog-optimize-thread-scheduling TRUE
binlog-row-event-max-size 1024
binlog-stmt-cache-size 32768
bulk-insert-buffer-size 8388608
@@ -764,7 +885,11 @@ connect-timeout 10
console FALSE
date-format %Y-%m-%d
datetime-format %Y-%m-%d %H:%i:%s
-default-storage-engine InnoDB
+deadlock-search-depth-long 15
+deadlock-search-depth-short 4
+deadlock-timeout-long 50000000
+deadlock-timeout-short 10000
+default-storage-engine myisam
default-time-zone (No default value)
default-week-format 0
delay-key-write ON
@@ -773,12 +898,14 @@ delayed-insert-timeout 300
delayed-queue-size 1000
disconnect-slave-event-count 0
div-precision-increment 4
-engine-condition-pushdown TRUE
+engine-condition-pushdown FALSE
event-scheduler OFF
expire-logs-days 0
external-locking FALSE
+extra-max-connections 1
+extra-port 0
flush FALSE
-flush-time 1800
+flush-time 0
ft-boolean-syntax + -><()~*:""&|
ft-max-word-len 84
ft-min-word-len 4
@@ -795,11 +922,14 @@ init-rpl-role MASTER
init-slave
interactive-timeout 28800
join-buffer-size 131072
+join-buffer-space-limit 2097152
+join-cache-level 1
keep-files-on-create FALSE
-key-buffer-size 8388608
+key-buffer-size 134217728
key-cache-age-threshold 300
key-cache-block-size 1024
key-cache-division-limit 100
+key-cache-segments 0
language MYSQL_SHAREDIR/
lc-messages en_US
lc-messages-dir MYSQL_SHAREDIR/
@@ -816,7 +946,10 @@ log-queries-not-using-indexes FALSE
log-short-format FALSE
log-slave-updates FALSE
log-slow-admin-statements FALSE
+log-slow-filter admin,filesort,filesort_on_disk,full_join,full_scan,query_cache,query_cache_miss,tmp_table,tmp_table_on_disk
+log-slow-rate-limit 1
log-slow-slave-statements FALSE
+log-slow-verbosity
log-tc tc.log
log-tc-size 24576
log-warnings 1
@@ -825,6 +958,7 @@ low-priority-updates FALSE
lower-case-table-names 1
master-info-file master.info
master-retry-count 86400
+master-verify-checksum FALSE
max-allowed-packet 1048576
max-binlog-cache-size 18446744073709547520
max-binlog-dump-events 0
@@ -848,12 +982,13 @@ max-user-connections 0
max-write-lock-count 18446744073709551615
memlock FALSE
min-examined-row-limit 0
+mrr-buffer-size 262144
multi-range-count 256
myisam-block-size 1024
myisam-data-pointer-size 6
myisam-max-sort-file-size 9223372036853727232
myisam-mmap-size 18446744073709551615
-myisam-recover-options OFF
+myisam-recover-options DEFAULT
myisam-repair-threads 1
myisam-sort-buffer-size 8388608
myisam-stats-method nulls_unequal
@@ -863,14 +998,13 @@ net-buffer-length 16384
net-read-timeout 30
net-retry-count 10
net-write-timeout 60
-new FALSE
old FALSE
old-alter-table FALSE
old-passwords FALSE
old-style-user-limits FALSE
optimizer-prune-level 1
optimizer-search-depth 62
-optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on
+optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
performance-schema FALSE
performance-schema-events-waits-history-long-size 10000
performance-schema-events-waits-history-size 10
@@ -888,14 +1022,17 @@ performance-schema-max-table-instances 50000
performance-schema-max-thread-classes 50
performance-schema-max-thread-instances 1000
plugin-load (No default value)
+plugin-maturity unknown
port 3306
port-open-timeout 0
preload-buffer-size 32768
profiling-history-size 15
+progress-report-time 56
query-alloc-block-size 8192
query-cache-limit 1048576
query-cache-min-res-unit 4096
query-cache-size 0
+query-cache-strip-comments FALSE
query-cache-type ON
query-cache-wlock-invalidate FALSE
query-prealloc-size 8192
@@ -909,11 +1046,13 @@ relay-log-info-file relay-log.info
relay-log-purge TRUE
relay-log-recovery FALSE
relay-log-space-limit 0
+replicate-annotate-row-events FALSE
replicate-same-server-id FALSE
report-host (No default value)
report-password (No default value)
report-port 3306
report-user (No default value)
+rowid-merge-buff-size 8388608
rpl-recovery-rank 0
safe-user-create FALSE
secure-auth FALSE
@@ -931,6 +1070,7 @@ slave-compressed-protocol FALSE
slave-exec-mode STRICT
slave-net-timeout 3600
slave-skip-errors (No default value)
+slave-sql-verify-checksum TRUE
slave-transaction-retries 10
slave-type-conversions
slow-launch-time 2
@@ -938,20 +1078,23 @@ slow-query-log FALSE
sort-buffer-size 2097152
sporadic-binlog-dump-fail FALSE
sql-mode
+stack-trace TRUE
symbolic-links FALSE
sync-binlog 0
-sync-frm TRUE
+sync-frm FALSE
sync-master-info 0
sync-relay-log 0
sync-relay-log-info 0
+sync-sys TRUE
sysdate-is-now FALSE
table-cache 400
table-definition-cache 400
table-open-cache 400
tc-heuristic-recover COMMIT
+thread-alarm TRUE
thread-cache-size 0
thread-handling one-thread-per-connection
-thread-stack 262144
+thread-stack 294912
time-format %H:%i:%s
timed-mutexes FALSE
tmp-table-size 16777216
@@ -959,6 +1102,7 @@ transaction-alloc-block-size 8192
transaction-isolation REPEATABLE-READ
transaction-prealloc-size 4096
updatable-views-with-limit YES
+userstat FALSE
verbose TRUE
wait-timeout 28800
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index 585d7a14ce9..916deeee1dd 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -148,10 +148,10 @@ insert into t1 values
(7,7), (8,8), (9,9), (10,10), (11,11), (12,12);
explain select * from t1 where a between 2 and 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx idx 4 NULL 2 Using where
+1 SIMPLE t1 range idx idx 4 NULL 2 Using index condition
explain select * from t1 where a between 2 and 3 or b is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx idx 4 NULL 2 Using where
+1 SIMPLE t1 range idx idx 4 NULL 2 Using index condition
drop table t1;
select cast(NULL as signed);
cast(NULL as signed)
diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result
index c7feaa5268d..4e28f73caad 100644
--- a/mysql-test/r/null_key.result
+++ b/mysql-test/r/null_key.result
@@ -76,13 +76,13 @@ insert into t2 select * from t1;
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
explain select * from t1 where a is null and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a is null and b = 2 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a is null and b = 7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a=2 and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 1 Using where
@@ -91,25 +91,25 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 12 Using where
explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 and c=0 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 5 NULL 5 Using where
+1 SIMPLE t1 range a,b a 5 NULL 5 Using index condition; Using where
explain select * from t1 where (a is null or a = 7) and b=7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref_or_null a,b a 5 const 4 Using where
+1 SIMPLE t1 ref_or_null a,b a 5 const 4 Using index condition; Using where
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 1 Using where
+1 SIMPLE t1 range a a 5 NULL 1 Using index condition
explain select * from t1 where a is null and b=7 or a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 5 NULL 4 Using where
+1 SIMPLE t1 range a,b a 5 NULL 4 Using index condition; Using where
explain select * from t1 where a > 8 and a < 9;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 1 Using where
+1 SIMPLE t1 range a a 5 NULL 1 Using index condition
explain select * from t1 where b like "6%";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 12 NULL 1 Using where
@@ -258,7 +258,7 @@ INSERT INTO t1 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4
INSERT INTO t2 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4),(9,NULL),(10,NULL);
explain select id from t1 where uniq_id is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref idx1 idx1 5 const 5 Using where
+1 SIMPLE t1 ref idx1 idx1 5 const 5 Using index condition
explain select id from t1 where uniq_id =1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const idx1 idx1 5 const 1
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 824e6f55ae0..f440094c5ee 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -515,7 +515,7 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.skr = t3.uid order by t1.gid,t3.skr;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.skr 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.skr 1 Using index condition
drop table t1,t2,t3;
CREATE TABLE t1 (
`titre` char(80) NOT NULL default '',
@@ -612,10 +612,10 @@ DS-MRR: use two IGNORE INDEX queries, otherwise we get cost races, because
DS-MRR: records_in_range/read_time return the same numbers for all three indexes
EXPLAIN SELECT * FROM t1 IGNORE INDEX (LongField, StringField) WHERE FieldKey > '2' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range FieldKey FieldKey 38 NULL 4 Using where; Using filesort
+1 SIMPLE t1 range FieldKey FieldKey 38 NULL 4 Using index condition; Using filesort
EXPLAIN SELECT * FROM t1 IGNORE INDEX (FieldKey, LongField) WHERE FieldKey > '2' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range StringField StringField 38 NULL 4 Using where; Using filesort
+1 SIMPLE t1 range StringField StringField 38 NULL 4 Using index condition; Using filesort
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
FieldKey LongVal StringVal
3 1 2
@@ -645,7 +645,7 @@ insert into t1 values (2, 1), (1, 1), (4, NULL), (3, NULL), (6, 2), (5, 2);
insert into t1 values (12, 11), (11, 11), (14, 3), (13, 5), (16, 12), (15, 12);
explain select * from t1 where b=1 or b is null order by a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref_or_null b b 5 const 4 Using where; Using filesort
+1 SIMPLE t1 ref_or_null b b 5 const 4 Using index condition; Using where; Using filesort
select * from t1 where b=1 or b is null order by a;
a b
1 1
@@ -654,7 +654,7 @@ a b
4 NULL
explain select * from t1 where b=2 or b is null order by a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref_or_null b b 5 const 3 Using where; Using filesort
+1 SIMPLE t1 ref_or_null b b 5 const 3 Using index condition; Using where; Using filesort
select * from t1 where b=2 or b is null order by a;
a b
3 NULL
@@ -1114,7 +1114,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index k2 k3 5 NULL 73 Using where
EXPLAIN SELECT id,c3 FROM t2 WHERE c2 BETWEEN 20 AND 30 ORDER BY c3 LIMIT 4000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range k2 k2 5 NULL 386 Using where; Using filesort
+1 SIMPLE t2 range k2 k2 5 NULL 386 Using index condition; Using filesort
SELECT id,c3 FROM t2 WHERE c2=11 ORDER BY c3 LIMIT 20;
id c3
6 14
@@ -1492,8 +1492,8 @@ SELECT d FROM t1, t2
WHERE t2.b=14 AND t2.a=t1.a AND 5.1<t2.c AND t1.b='DE'
ORDER BY t2.c LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b b 4 const 4 Using where; Using temporary; Using filesort
-1 SIMPLE t2 ref a,b,c a 40 test.t1.a,const 11 Using where
+1 SIMPLE t1 ref a,b b 4 const 4 Using index condition; Using where; Using temporary; Using filesort
+1 SIMPLE t2 ref a,b,c a 40 test.t1.a,const 11 Using index condition
SELECT d FROM t1, t2
WHERE t2.b=14 AND t2.a=t1.a AND 5.1<t2.c AND t1.b='DE'
ORDER BY t2.c LIMIT 1;
@@ -1628,19 +1628,19 @@ INSERT INTO t2 SELECT a+4, b FROM t2;
EXPLAIN
SELECT * FROM t1 FORCE INDEX FOR ORDER BY (a), t2 WHERE t1.a < 2 ORDER BY t1.a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 2 Using where; Using temporary; Using filesort
+1 SIMPLE t1 range a a 5 NULL 2 Using index condition; Using temporary; Using filesort
1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join)
# should have "using filesort"
EXPLAIN
SELECT * FROM t1 USE INDEX FOR ORDER BY (a), t2 WHERE t1.a < 2 ORDER BY t1.a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 2 Using where; Using temporary; Using filesort
+1 SIMPLE t1 range a a 5 NULL 2 Using index condition; Using temporary; Using filesort
1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join)
# should have "using filesort"
EXPLAIN
SELECT * FROM t1 FORCE INDEX FOR JOIN (a), t2 WHERE t1.a < 2 ORDER BY t1.a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 2 Using where; Using temporary; Using filesort
+1 SIMPLE t1 range a a 5 NULL 2 Using index condition; Using temporary; Using filesort
1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join)
DROP TABLE t1, t2;
#
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 18d698447c4..aed3274e732 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -3765,3 +3765,64 @@ date('2010-10-10') between '2010-09-09' and ?
execute stmt using @a;
date('2010-10-10') between '2010-09-09' and ?
0
+#
+# Bug #892725: look-up is changed for a full scan when executing PS
+#
+create table t1 (a int primary key, b int);
+insert into t1 values
+(7,70), (3,40), (4,40), (8,70), (1,70), (9,50), (2,70);
+prepare st from 'select * from t1 where a=8';
+flush status;
+execute st;
+a b
+8 70
+show status like '%Handler_read%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 0
+flush status;
+execute st;
+a b
+8 70
+show status like '%Handler_read%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 0
+flush status;
+select * from t1 use index() where a=3;
+a b
+3 40
+show status like '%Handler_read%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 0
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 8
+flush status;
+execute st;
+a b
+8 70
+show status like '%Handler_read%';
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 0
+deallocate prepare st;
+drop table t1;
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index 1c823d01480..a32f048977c 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -467,9 +467,9 @@ def key 253 64 7 Y 0 31 8
def key_len 253 4096 1 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 253 255 27 N 1 31 8
+def Extra 253 255 37 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where; Using filesort
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using index condition; Using filesort
drop table if exists t2;
create table t2 (id smallint, name varchar(20)) ;
prepare stmt1 from ' insert into t2 values(?, ?) ' ;
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index 1c6845ef07e..a6b48403029 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -221,27 +221,27 @@ update t1 set y=x;
explain select * from t1, t1 t2 where t1.y = 8 and t2.x between 7 and t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1
-1 SIMPLE t2 range x x 5 NULL 2 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using join buffer (flat, BNL join)
explain select * from t1, t1 t2 where t1.y = 8 and t2.x >= 7 and t2.x <= t1.y+0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1
-1 SIMPLE t2 range x x 5 NULL 2 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using join buffer (flat, BNL join)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1
-1 SIMPLE t2 range x x 5 NULL 3 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t2 range x x 5 NULL 3 Using index condition; Using join buffer (flat, BNL join)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1
-1 SIMPLE t2 range x x 5 NULL 3 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t2 range x x 5 NULL 3 Using index condition; Using join buffer (flat, BNL join)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 0 and t1.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1
-1 SIMPLE t2 range x x 5 NULL 2 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using join buffer (flat, BNL join)
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 0 and t2.x <= t1.y;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1
-1 SIMPLE t2 range x x 5 NULL 2 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t2 range x x 5 NULL 2 Using index condition; Using join buffer (flat, BNL join)
explain select count(*) from t1 where x in (1);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref x x 5 const 1 Using index
@@ -276,7 +276,7 @@ INSERT INTO t1 VALUES
(33,5),(33,5),(33,5),(33,5),(34,5),(35,5);
EXPLAIN SELECT * FROM t1 WHERE a IN(1,2) AND b=5;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 5 NULL 2 Using where
+1 SIMPLE t1 range a,b a 5 NULL 2 Using index condition; Using where
SELECT * FROM t1 WHERE a IN(1,2) AND b=5;
a b
DROP TABLE t1;
@@ -421,19 +421,19 @@ test.t1 analyze status OK
test.t2 analyze status Table is already up to date
explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range uid_index uid_index 4 NULL 112 Using where
+1 SIMPLE t1 range uid_index uid_index 4 NULL 112 Using index condition
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid > 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range uid_index uid_index 4 NULL 112 Using where
+1 SIMPLE t1 range uid_index uid_index 4 NULL 112 Using index condition
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
explain select * from t1, t2 where t1.uid=t2.uid AND t1.uid != 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range uid_index uid_index 4 NULL 113 Using where
+1 SIMPLE t1 range uid_index uid_index 4 NULL 113 Using index condition
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
explain select * from t1, t2 where t1.uid=t2.uid AND t2.uid != 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range uid_index uid_index 4 NULL 113 Using where
+1 SIMPLE t1 range uid_index uid_index 4 NULL 113 Using index condition
1 SIMPLE t2 ref uid_index uid_index 4 test.t1.uid 38
select * from t1, t2 where t1.uid=t2.uid AND t1.uid > 0;
id name uid id name uid
@@ -615,13 +615,13 @@ INSERT INTO t1 (a) VALUES
('111'),('222'),('222'),('222'),('222'),('444'),('aaa'),('AAA'),('bbb');
explain select * from t1 where a='aaa';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 11 const 2 Using where
+1 SIMPLE t1 ref a a 11 const 2 Using index condition
explain select * from t1 where a=binary 'aaa';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 11 NULL 2 Using where
+1 SIMPLE t1 range a a 11 NULL 2 Using index condition
explain select * from t1 where a='aaa' collate latin1_bin;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 11 NULL 2 Using where
+1 SIMPLE t1 range a a 11 NULL 2 Using index condition
explain select * from t1 where a='aaa' collate latin1_german1_ci;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a NULL NULL NULL 9 Using where
@@ -716,7 +716,7 @@ WHERE s.oxrootid = 'd8c4177d09f8b11f5.52725521' AND
v.oxrootid ='d8c4177d09f8b11f5.52725521' AND
s.oxleft > v.oxleft AND s.oxleft < v.oxright;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE v ref OXLEFT,OXRIGHT,OXROOTID OXROOTID 34 const 5 Using where
+1 SIMPLE v ref OXLEFT,OXRIGHT,OXROOTID OXROOTID 34 const 5 Using index condition
1 SIMPLE s ALL OXLEFT NULL NULL NULL 12 Range checked for each record (index map: 0x4)
SELECT s.oxid FROM t1 v, t1 s
WHERE s.oxrootid = 'd8c4177d09f8b11f5.52725521' AND
@@ -890,10 +890,10 @@ INSERT INTO t1 VALUES
(55,'C'), (56,'C'), (57,'C'), (58,'C'), (59,'C'), (60,'C');
EXPLAIN SELECT * FROM t1 WHERE status <> 'A' AND status <> 'B';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range status status 23 NULL 11 Using where
+1 SIMPLE t1 range status status 23 NULL 11 Using index condition
EXPLAIN SELECT * FROM t1 WHERE status NOT IN ('A','B');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range status status 23 NULL 11 Using where
+1 SIMPLE t1 range status status 23 NULL 11 Using index condition
SELECT * FROM t1 WHERE status <> 'A' AND status <> 'B';
id status
53 C
@@ -922,10 +922,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range status status 23 NULL 11 Using where; Using index
EXPLAIN SELECT * FROM t1 WHERE status NOT BETWEEN 'A' AND 'B';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range status status 23 NULL 10 Using where
+1 SIMPLE t1 range status status 23 NULL 10 Using index condition
EXPLAIN SELECT * FROM t1 WHERE status < 'A' OR status > 'B';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range status status 23 NULL 10 Using where
+1 SIMPLE t1 range status status 23 NULL 10 Using index condition; Using where
SELECT * FROM t1 WHERE status NOT BETWEEN 'A' AND 'B';
id status
53 C
@@ -1026,20 +1026,20 @@ create table t2 (a varchar(10), filler char(200), key(a));
insert into t2 select * from t1;
explain select * from t1 where a between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 13 NULL # Using where
+1 SIMPLE t1 range a a 13 NULL # Using index condition
explain select * from t1 where a = 'a' or a='a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 13 NULL # Using where
+1 SIMPLE t1 range a a 13 NULL # Using index condition; Using where
explain select * from t2 where a between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref a a 13 const # Using where
+1 SIMPLE t2 ref a a 13 const # Using index condition
explain select * from t2 where a = 'a' or a='a ';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref a a 13 const # Using where
+1 SIMPLE t2 ref a a 13 const # Using index condition; Using where
update t1 set a='b' where a<>'a';
explain select * from t1 where a not between 'b' and 'b';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 13 NULL # Using where
+1 SIMPLE t1 range a a 13 NULL # Using index condition
select a, hex(filler) from t1 where a not between 'b' and 'b';
a hex(filler)
a 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
@@ -1083,7 +1083,7 @@ id b c
0 3 4
EXPLAIN SELECT * FROM t1 WHERE b<=3 AND 3<=c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 3 Using where
+1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 3 Using index condition; Using where
EXPLAIN SELECT * FROM t1 WHERE 3 BETWEEN b AND c;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range idx1,idx2 idx2 4 NULL 3 Using where
@@ -1115,7 +1115,7 @@ INSERT INTO t1 VALUES
('A2','2005-12-01 08:00:00',1000);
EXPLAIN SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref PRIMARY PRIMARY 20 const 2 Using where
+1 SIMPLE t1 ref PRIMARY PRIMARY 20 const 2 Using index condition
SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00';
item started price
Warnings:
@@ -1153,7 +1153,7 @@ INSERT INTO t1 VALUES
This must use range access:
explain select * from t1 where dateval >= '2007-01-01 00:00:00' and dateval <= '2007-01-02 23:59:59';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range dateval dateval 4 NULL 2 Using where
+1 SIMPLE t1 range dateval dateval 4 NULL 2 Using index condition
drop table t1;
CREATE TABLE t1 (
a varchar(32), index (a)
@@ -1219,7 +1219,7 @@ Z
In following EXPLAIN the access method should be ref, #rows~=500 (and not 2)
explain select * from t2 where a=1000 and b<11;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref a a 5 const 502 Using where
+1 SIMPLE t2 ref a a 5 const 502 Using index condition
drop table t1, t2;
CREATE TABLE t1( a INT, b INT, KEY( a, b ) );
CREATE TABLE t2( a INT, b INT, KEY( a, b ) );
@@ -1690,7 +1690,7 @@ pk i4
EXPLAIN
SELECT * FROM t1 WHERE 10 BETWEEN 10 AND i4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range i4_uq i4_uq 5 NULL 3 Using where
+1 SIMPLE t1 range i4_uq i4_uq 5 NULL 3 Using index condition
SELECT * FROM t1 WHERE 10 BETWEEN 10 AND i4;
pk i4
1 10
@@ -1699,7 +1699,7 @@ pk i4
EXPLAIN
SELECT * FROM t1 WHERE 10 BETWEEN i4 AND 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range i4_uq i4_uq 5 NULL 1 Using where
+1 SIMPLE t1 range i4_uq i4_uq 5 NULL 1 Using index condition
SELECT * FROM t1 WHERE 10 BETWEEN i4 AND 10;
pk i4
1 10
@@ -1733,7 +1733,7 @@ pk i4
EXPLAIN
SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 99999999999999999;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range i4_uq i4_uq 5 NULL 2 Using where
+1 SIMPLE t1 range i4_uq i4_uq 5 NULL 2 Using index condition
SELECT * FROM t1 WHERE i4 BETWEEN 10 AND 99999999999999999;
pk i4
1 10
@@ -1748,7 +1748,7 @@ pk i4
EXPLAIN
SELECT * FROM t1 WHERE i4 BETWEEN 10 AND '20';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range i4_uq i4_uq 5 NULL 1 Using where
+1 SIMPLE t1 range i4_uq i4_uq 5 NULL 1 Using index condition
SELECT * FROM t1 WHERE i4 BETWEEN 10 AND '20';
pk i4
1 10
@@ -1757,14 +1757,14 @@ EXPLAIN
SELECT * FROM t1, t1 as t2 WHERE t2.pk BETWEEN t1.i4 AND t1.i4;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL i4_uq NULL NULL NULL 3
-1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.i4 1 Using where
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.i4 1 Using index condition
SELECT * FROM t1, t1 as t2 WHERE t2.pk BETWEEN t1.i4 AND t1.i4;
pk i4 pk i4
EXPLAIN
SELECT * FROM t1, t1 as t2 WHERE t1.i4 BETWEEN t2.pk AND t2.pk;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL i4_uq NULL NULL NULL 3
-1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.i4 1 Using where
+1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.i4 1 Using index condition
SELECT * FROM t1, t1 as t2 WHERE t1.i4 BETWEEN t2.pk AND t2.pk;
pk i4 pk i4
DROP TABLE t1;
@@ -1793,7 +1793,7 @@ INSERT INTO t100(I,J) VALUES(8,26);
EXPLAIN SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t100 range I I 10 NULL 4 Using where
+1 SIMPLE t100 range I I 10 NULL 4 Using index condition; Using where
SELECT * FROM t100 WHERE I <> 6 OR (I <> 8 AND J = 5);
K I J
diff --git a/mysql-test/r/range_vs_index_merge.result b/mysql-test/r/range_vs_index_merge.result
index f1838bc9aae..f8738457dd9 100644
--- a/mysql-test/r/range_vs_index_merge.result
+++ b/mysql-test/r/range_vs_index_merge.result
@@ -49,14 +49,14 @@ SELECT * FROM City
WHERE (Population >= 100000 OR Name LIKE 'P%') AND Country='CAN' OR
(Population < 100000 OR Name Like 'T%') AND Country='ARG';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Country,Name Country 3 NULL 104 Using where
+1 SIMPLE City range Population,Country,Name Country 3 NULL 104 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE Population < 200000 AND Name LIKE 'P%' AND
(Population > 300000 OR Name LIKE 'T%') AND
(Population < 100000 OR Name LIKE 'Pa%');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Name Name 35 NULL 135 Using where
+1 SIMPLE City range Population,Name Name 35 NULL 135 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE Population > 100000 AND Name LIKE 'Aba%' OR
@@ -69,12 +69,12 @@ EXPLAIN
SELECT * FROM City
WHERE (Population > 101000 AND Population < 115000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 459 Using where
+1 SIMPLE City range Population Population 4 NULL 459 Using index condition
EXPLAIN
SELECT * FROM City
WHERE (Population > 101000 AND Population < 102000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 39 Using where
+1 SIMPLE City range Population Population 4 NULL 39 Using index condition
EXPLAIN
SELECT * FROM City
WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'F'));
@@ -91,7 +91,7 @@ SELECT * FROM City
WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'F'))
AND (Population > 101000 AND Population < 102000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Country,Name Population 4 NULL 39 Using where
+1 SIMPLE City range Population,Country,Name Population 4 NULL 39 Using index condition; Using where
SELECT * FROM City USE INDEX ()
WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'F'))
AND (Population > 101000 AND Population < 115000);
@@ -171,37 +171,37 @@ ID Name Country Population
EXPLAIN
SELECT * FROM City WHERE (Name < 'Ac');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 13 Using where
+1 SIMPLE City range Name Name 35 NULL 13 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Name < 'Bb');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 208 Using where
+1 SIMPLE City range Name Name 35 NULL 208 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Country > 'A' AND Country < 'B');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Country Country 3 NULL 104 Using where
+1 SIMPLE City range Country Country 3 NULL 104 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Name BETWEEN 'P' AND 'Pb');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 39 Using where
+1 SIMPLE City range Name Name 35 NULL 39 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Name BETWEEN 'P' AND 'S');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 221 Using where
+1 SIMPLE City range Name Name 35 NULL 221 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 101000 AND Population < 110000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 328 Using where
+1 SIMPLE City range Population Population 4 NULL 328 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 103000 AND Population < 104000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 37 Using where
+1 SIMPLE City range Population Population 4 NULL 37 Using index condition
EXPLAIN
SELECT * FROM City
WHERE (Name < 'Ac' AND (Country > 'A' AND Country < 'B')) OR
(Name BETWEEN 'P' AND 'Pb' AND (Population > 101000 AND Population < 110000));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Country,Name Name 35 NULL 52 Using where
+1 SIMPLE City range Population,Country,Name Name 35 NULL 52 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE (Name < 'Ac' AND (Country > 'A' AND Country < 'B')) OR
@@ -327,11 +327,11 @@ ID Name Country Population
EXPLAIN
SELECT * FROM City WHERE (ID < 10) OR (ID BETWEEN 100 AND 110);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 21 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 21 Using index condition; Using where
EXPLAIN
SELECT * FROM City WHERE (ID < 200) OR (ID BETWEEN 100 AND 200);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 201 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 201 Using index condition; Using where
EXPLAIN
SELECT * FROM City WHERE (ID < 600) OR (ID BETWEEN 900 AND 1500);
id select_type table type possible_keys key key_len ref rows Extra
@@ -339,22 +339,22 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN
SELECT * FROM City WHERE Country > 'A' AND Country < 'ARG';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Country Country 3 NULL 19 Using where
+1 SIMPLE City range Country Country 3 NULL 19 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'H%' OR Name LIKE 'P%' ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 222 Using where
+1 SIMPLE City range Name Name 35 NULL 222 Using index condition; Using where
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'Ha%' OR Name LIKE 'Pa%' ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 72 Using where
+1 SIMPLE City range Name Name 35 NULL 72 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE ((ID < 10) AND (Name LIKE 'H%' OR (Country > 'A' AND Country < 'ARG')))
OR ((ID BETWEEN 100 AND 110) AND
(Name LIKE 'P%' OR (Population > 103000 AND Population < 104000)));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country,Name PRIMARY 4 NULL 21 Using where
+1 SIMPLE City range PRIMARY,Population,Country,Name PRIMARY 4 NULL 21 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE ((ID < 800) AND (Name LIKE 'Ha%' OR (Country > 'A' AND Country < 'ARG')))
@@ -576,39 +576,39 @@ ID Name Country Population
EXPLAIN
SELECT * FROM City WHERE Population > 101000 AND Population < 102000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 39 Using where
+1 SIMPLE City range Population Population 4 NULL 39 Using index condition
EXPLAIN
SELECT * FROM City WHERE Population > 101000 AND Population < 110000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 328 Using where
+1 SIMPLE City range Population Population 4 NULL 328 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country < 'C';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Country Country 3 NULL 436 Using where
+1 SIMPLE City range Country Country 3 NULL 436 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country < 'AGO';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Country Country 3 NULL 6 Using where
+1 SIMPLE City range Country Country 3 NULL 6 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name BETWEEN 'P' AND 'S';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 221 Using where
+1 SIMPLE City range Name Name 35 NULL 221 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name BETWEEN 'P' AND 'Pb';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 39 Using where
+1 SIMPLE City range Name Name 35 NULL 39 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 3400 AND 3800;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 401 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 401 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 3790 AND 3800;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'P%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 135 Using where
+1 SIMPLE City range Name Name 35 NULL 135 Using index condition
EXPLAIN
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 102000) AND
@@ -679,23 +679,23 @@ CREATE INDEX CountryPopulation ON City(Country,Population);
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'Pas%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 5 Using where
+1 SIMPLE City range Name Name 35 NULL 5 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'P%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 135 Using where
+1 SIMPLE City range Name Name 35 NULL 135 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 101000 AND Population < 103000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 81 Using where
+1 SIMPLE City range Population Population 4 NULL 81 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country='USA';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation Country 3 const 267 Using where
+1 SIMPLE City ref Country,CountryPopulation Country 3 const 267 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country='FIN';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation Country 3 const 6 Using where
+1 SIMPLE City ref Country,CountryPopulation Country 3 const 6 Using index condition
EXPLAIN
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 103000) OR Name LIKE 'Pas%')
@@ -707,7 +707,7 @@ SELECT * FROM City
WHERE ((Population > 101000 AND Population < 103000) OR Name LIKE 'P%')
AND Country='FIN';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Population,Country,Name,CountryPopulation Country 3 const 6 Using where
+1 SIMPLE City ref Population,Country,Name,CountryPopulation Country 3 const 6 Using index condition; Using where
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 103000) OR Name LIKE 'Pas%')
AND Country='USA';
@@ -752,51 +752,51 @@ CREATE INDEX CountryName ON City(Country,Name);
EXPLAIN
SELECT * FROM City WHERE Country='USA';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation,CountryName Country 3 const 267 Using where
+1 SIMPLE City ref Country,CountryPopulation,CountryName Country 3 const 267 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country='FIN';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation,CountryName CountryName 3 const 5 Using where
+1 SIMPLE City ref Country,CountryPopulation,CountryName CountryName 3 const 5 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country='BRA';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation,CountryName CountryName 3 const 221 Using where
+1 SIMPLE City ref Country,CountryPopulation,CountryName CountryName 3 const 221 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 3790 AND 3800;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 4025 AND 4035;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 4028 AND 4032;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 5 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 5 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 3500 AND 3800;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 301 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 301 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 4000 AND 4300;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 80 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 80 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 250 and 260 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 101000 AND Population < 102000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 39 Using where
+1 SIMPLE City range Population Population 4 NULL 39 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 101000 AND Population < 103000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 81 Using where
+1 SIMPLE City range Population Population 4 NULL 81 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'Pa%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 41 Using where
+1 SIMPLE City range Name Name 35 NULL 41 Using index condition
EXPLAIN
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 102000) OR
@@ -817,7 +817,7 @@ WHERE ((Population > 101000 AND Population < 110000) OR
ID BETWEEN 3500 AND 3800) AND Country='FIN'
AND (Name BETWEEN 'P' AND 'T' OR ID BETWEEN 4000 AND 4300);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref PRIMARY,Population,Country,Name,CountryPopulation,CountryName CountryName 3 const 5 Using where
+1 SIMPLE City ref PRIMARY,Population,Country,Name,CountryPopulation,CountryName CountryName 3 const 5 Using index condition; Using where
SELECT * FROM City USE INDEX ()
WHERE ((Population > 101000 AND Population < 102000) OR
ID BETWEEN 3790 AND 3800) AND Country='USA'
@@ -949,7 +949,7 @@ WHERE ((Population > 101000 AND Population < 11000) OR
ID BETWEEN 3500 AND 3800) AND Country='USA'
AND (Name LIKE 'P%' OR ID BETWEEN 4000 AND 4300);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country,Name,CountryPopulation,CountryName CountryName 38 NULL 23 Using where
+1 SIMPLE City range PRIMARY,Population,Country,Name,CountryPopulation,CountryName CountryName 38 NULL 23 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 11000) OR
@@ -1414,4 +1414,30 @@ a b c d
0 75 5 3
SET SESSION optimizer_switch=DEFAULT;
DROP TABLE t1;
+CREATE TABLE t1 (a int NOT NULL PRIMARY KEY, b int, c int, INDEX idx(c,b));
+INSERT INTO t1 VALUES (19,1,NULL), (20,5,7);
+EXPLAIN
+SELECT * FROM t1
+WHERE t1.a>300 AND t1.c!=0 AND t1.b>=350 AND t1.b<=400 AND
+(t1.c=0 OR t1.a=500);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,idx PRIMARY 4 NULL 1 Using index condition; Using where
+SELECT * FROM t1
+WHERE t1.a>300 AND t1.c!=0 AND t1.b>=350 AND t1.b<=400 AND
+(t1.c=0 OR t1.a=500);
+a b c
+DROP TABLE t1;
+CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX idx(b));
+INSERT INTO t1 VALUES (167,9999), (168,10000);
+EXPLAIN
+SELECT * FROM t1
+WHERE a BETWEEN 4 AND 5 AND b IN (255,4) OR a IN (2,14,25) OR a!=2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL PRIMARY,idx NULL NULL NULL 2 Using where
+SELECT * FROM t1
+WHERE a BETWEEN 4 AND 5 AND b IN (255,4) OR a IN (2,14,25) OR a!=2;
+a b
+167 9999
+168 10000
+DROP TABLE t1;
set session optimizer_switch='index_merge_sort_intersection=default';
diff --git a/mysql-test/r/range_vs_index_merge_innodb.result b/mysql-test/r/range_vs_index_merge_innodb.result
index 71a4fcf9690..57862ded4f2 100644
--- a/mysql-test/r/range_vs_index_merge_innodb.result
+++ b/mysql-test/r/range_vs_index_merge_innodb.result
@@ -50,14 +50,14 @@ SELECT * FROM City
WHERE (Population >= 100000 OR Name LIKE 'P%') AND Country='CAN' OR
(Population < 100000 OR Name Like 'T%') AND Country='ARG';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Country,Name Country 3 NULL 106 Using where
+1 SIMPLE City range Population,Country,Name Country 3 NULL 106 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE Population < 200000 AND Name LIKE 'P%' AND
(Population > 300000 OR Name LIKE 'T%') AND
(Population < 100000 OR Name LIKE 'Pa%');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Name Name 35 NULL 235 Using where
+1 SIMPLE City range Population,Name Name 35 NULL 235 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE Population > 100000 AND Name LIKE 'Aba%' OR
@@ -70,12 +70,12 @@ EXPLAIN
SELECT * FROM City
WHERE (Population > 101000 AND Population < 115000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 458 Using where
+1 SIMPLE City range Population Population 4 NULL 458 Using index condition
EXPLAIN
SELECT * FROM City
WHERE (Population > 101000 AND Population < 102000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 38 Using where
+1 SIMPLE City range Population Population 4 NULL 38 Using index condition
EXPLAIN
SELECT * FROM City
WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'F'));
@@ -92,7 +92,7 @@ SELECT * FROM City
WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'F'))
AND (Population > 101000 AND Population < 102000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Country,Name Population 4 NULL 38 Using where
+1 SIMPLE City range Population,Country,Name Population 4 NULL 38 Using index condition; Using where
SELECT * FROM City USE INDEX ()
WHERE ((Name > 'Ca' AND Name < 'Cf') OR (Country > 'E' AND Country < 'F'))
AND (Population > 101000 AND Population < 115000);
@@ -172,37 +172,37 @@ ID Name Country Population
EXPLAIN
SELECT * FROM City WHERE (Name < 'Ac');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 23 Using where
+1 SIMPLE City range Name Name 35 NULL 23 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Name < 'Bb');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 373 Using where
+1 SIMPLE City range Name Name 35 NULL 373 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Country > 'A' AND Country < 'B');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Country Country 3 NULL 106 Using where
+1 SIMPLE City range Country Country 3 NULL 106 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Name BETWEEN 'P' AND 'Pb');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 71 Using where
+1 SIMPLE City range Name Name 35 NULL 71 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Name BETWEEN 'P' AND 'S');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 384 Using where
+1 SIMPLE City range Name Name 35 NULL 384 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 101000 AND Population < 110000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 327 Using where
+1 SIMPLE City range Population Population 4 NULL 327 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 103000 AND Population < 104000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 36 Using where
+1 SIMPLE City range Population Population 4 NULL 36 Using index condition
EXPLAIN
SELECT * FROM City
WHERE (Name < 'Ac' AND (Country > 'A' AND Country < 'B')) OR
(Name BETWEEN 'P' AND 'Pb' AND (Population > 101000 AND Population < 110000));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population,Country,Name Name 35 NULL 94 Using where
+1 SIMPLE City range Population,Country,Name Name 35 NULL 94 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE (Name < 'Ac' AND (Country > 'A' AND Country < 'B')) OR
@@ -328,34 +328,34 @@ ID Name Country Population
EXPLAIN
SELECT * FROM City WHERE (ID < 10) OR (ID BETWEEN 100 AND 110);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 20 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 20 Using index condition; Using where
EXPLAIN
SELECT * FROM City WHERE (ID < 200) OR (ID BETWEEN 100 AND 200);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 200 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 200 Using index condition; Using where
EXPLAIN
SELECT * FROM City WHERE (ID < 600) OR (ID BETWEEN 900 AND 1500);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 1198 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 1198 Using index condition; Using where
EXPLAIN
SELECT * FROM City WHERE Country > 'A' AND Country < 'ARG';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Country Country 3 NULL 19 Using where
+1 SIMPLE City range Country Country 3 NULL 19 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'H%' OR Name LIKE 'P%' ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 394 Using where
+1 SIMPLE City range Name Name 35 NULL 394 Using index condition; Using where
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'Ha%' OR Name LIKE 'Pa%' ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 133 Using where
+1 SIMPLE City range Name Name 35 NULL 133 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE ((ID < 10) AND (Name LIKE 'H%' OR (Country > 'A' AND Country < 'ARG')))
OR ((ID BETWEEN 100 AND 110) AND
(Name LIKE 'P%' OR (Population > 103000 AND Population < 104000)));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country,Name PRIMARY 4 NULL 20 Using where
+1 SIMPLE City range PRIMARY,Population,Country,Name PRIMARY 4 NULL 20 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE ((ID < 800) AND (Name LIKE 'Ha%' OR (Country > 'A' AND Country < 'ARG')))
@@ -369,7 +369,7 @@ WHERE ((ID < 200) AND (Name LIKE 'Ha%' OR (Country > 'A' AND Country < 'ARG')))
OR ((ID BETWEEN 100 AND 200) AND
(Name LIKE 'Pa%' OR (Population > 103000 AND Population < 104000)));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country,Name PRIMARY 4 NULL 200 Using where
+1 SIMPLE City range PRIMARY,Population,Country,Name PRIMARY 4 NULL 200 Using index condition; Using where
SELECT * FROM City USE INDEX ()
WHERE ((ID < 10) AND (Name LIKE 'H%' OR (Country > 'A' AND Country < 'ARG')))
OR ((ID BETWEEN 100 AND 110) AND
@@ -577,39 +577,39 @@ ID Name Country Population
EXPLAIN
SELECT * FROM City WHERE Population > 101000 AND Population < 102000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 38 Using where
+1 SIMPLE City range Population Population 4 NULL 38 Using index condition
EXPLAIN
SELECT * FROM City WHERE Population > 101000 AND Population < 110000;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 327 Using where
+1 SIMPLE City range Population Population 4 NULL 327 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country < 'C';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Country Country 3 NULL 446 Using where
+1 SIMPLE City range Country Country 3 NULL 446 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country < 'AGO';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Country Country 3 NULL 5 Using where
+1 SIMPLE City range Country Country 3 NULL 5 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name BETWEEN 'P' AND 'S';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 384 Using where
+1 SIMPLE City range Name Name 35 NULL 384 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name BETWEEN 'P' AND 'Pb';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 71 Using where
+1 SIMPLE City range Name Name 35 NULL 71 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 3400 AND 3800;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 400 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 400 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 3790 AND 3800;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'P%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 235 Using where
+1 SIMPLE City range Name Name 35 NULL 235 Using index condition
EXPLAIN
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 102000) AND
@@ -680,23 +680,23 @@ CREATE INDEX CountryPopulation ON City(Country,Population);
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'Pas%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 8 Using where
+1 SIMPLE City range Name Name 35 NULL 8 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'P%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 235 Using where
+1 SIMPLE City range Name Name 35 NULL 235 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 101000 AND Population < 103000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 80 Using where
+1 SIMPLE City range Population Population 4 NULL 80 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country='USA';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation Country 3 const 274 Using where
+1 SIMPLE City ref Country,CountryPopulation Country 3 const 274 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country='FIN';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation Country 3 const 7 Using where
+1 SIMPLE City ref Country,CountryPopulation Country 3 const 7 Using index condition
EXPLAIN
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 103000) OR Name LIKE 'Pas%')
@@ -708,7 +708,7 @@ SELECT * FROM City
WHERE ((Population > 101000 AND Population < 103000) OR Name LIKE 'P%')
AND Country='FIN';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Population,Country,Name,CountryPopulation Country 3 const 7 Using where
+1 SIMPLE City ref Population,Country,Name,CountryPopulation Country 3 const 7 Using index condition; Using where
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 103000) OR Name LIKE 'Pas%')
AND Country='USA';
@@ -753,51 +753,51 @@ CREATE INDEX CountryName ON City(Country,Name);
EXPLAIN
SELECT * FROM City WHERE Country='USA';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation,CountryName Country 3 const 274 Using where
+1 SIMPLE City ref Country,CountryPopulation,CountryName Country 3 const 274 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country='FIN';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation,CountryName Country 3 const 7 Using where
+1 SIMPLE City ref Country,CountryPopulation,CountryName Country 3 const 7 Using index condition
EXPLAIN
SELECT * FROM City WHERE Country='BRA';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref Country,CountryPopulation,CountryName Country 3 const 250 Using where
+1 SIMPLE City ref Country,CountryPopulation,CountryName Country 3 const 250 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 3790 AND 3800;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 4025 AND 4035;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 4028 AND 4032;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 5 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 5 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 3500 AND 3800;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 300 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 300 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 4000 AND 4300;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 80 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 80 Using index condition
EXPLAIN
SELECT * FROM City WHERE ID BETWEEN 250 and 260 ;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using where
+1 SIMPLE City range PRIMARY PRIMARY 4 NULL 11 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 101000 AND Population < 102000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 38 Using where
+1 SIMPLE City range Population Population 4 NULL 38 Using index condition
EXPLAIN
SELECT * FROM City WHERE (Population > 101000 AND Population < 103000);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Population Population 4 NULL 80 Using where
+1 SIMPLE City range Population Population 4 NULL 80 Using index condition
EXPLAIN
SELECT * FROM City WHERE Name LIKE 'Pa%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range Name Name 35 NULL 71 Using where
+1 SIMPLE City range Name Name 35 NULL 71 Using index condition
EXPLAIN
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 102000) OR
@@ -818,7 +818,7 @@ WHERE ((Population > 101000 AND Population < 110000) OR
ID BETWEEN 3500 AND 3800) AND Country='FIN'
AND (Name BETWEEN 'P' AND 'T' OR ID BETWEEN 4000 AND 4300);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City ref PRIMARY,Population,Country,Name,CountryPopulation,CountryName Country 3 const 7 Using where
+1 SIMPLE City ref PRIMARY,Population,Country,Name,CountryPopulation,CountryName Country 3 const 7 Using index condition; Using where
SELECT * FROM City USE INDEX ()
WHERE ((Population > 101000 AND Population < 102000) OR
ID BETWEEN 3790 AND 3800) AND Country='USA'
@@ -950,14 +950,14 @@ WHERE ((Population > 101000 AND Population < 11000) OR
ID BETWEEN 3500 AND 3800) AND Country='USA'
AND (Name LIKE 'P%' OR ID BETWEEN 4000 AND 4300);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country,Name,CountryPopulation,CountryName CountryName 38 NULL 18 Using where
+1 SIMPLE City range PRIMARY,Population,Country,Name,CountryPopulation,CountryName CountryName 38 NULL 18 Using index condition; Using where
EXPLAIN
SELECT * FROM City
WHERE ((Population > 101000 AND Population < 11000) OR
ID BETWEEN 3500 AND 3800) AND Country='USA'
AND (Name LIKE 'Pho%' OR ID BETWEEN 4000 AND 4300);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE City range PRIMARY,Population,Country,Name,CountryPopulation,CountryName Name 35 NULL 1 Using where
+1 SIMPLE City range PRIMARY,Population,Country,Name,CountryPopulation,CountryName Name 35 NULL 1 Using index condition; Using where
SELECT * FROM City USE INDEX ()
WHERE ((Population > 101000 AND Population < 11000) OR
ID BETWEEN 3500 AND 3800) AND Country='USA'
@@ -1415,5 +1415,31 @@ a b c d
0 75 5 3
SET SESSION optimizer_switch=DEFAULT;
DROP TABLE t1;
+CREATE TABLE t1 (a int NOT NULL PRIMARY KEY, b int, c int, INDEX idx(c,b));
+INSERT INTO t1 VALUES (19,1,NULL), (20,5,7);
+EXPLAIN
+SELECT * FROM t1
+WHERE t1.a>300 AND t1.c!=0 AND t1.b>=350 AND t1.b<=400 AND
+(t1.c=0 OR t1.a=500);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY,idx PRIMARY 4 NULL 1 Using index condition; Using where
+SELECT * FROM t1
+WHERE t1.a>300 AND t1.c!=0 AND t1.b>=350 AND t1.b<=400 AND
+(t1.c=0 OR t1.a=500);
+a b c
+DROP TABLE t1;
+CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX idx(b));
+INSERT INTO t1 VALUES (167,9999), (168,10000);
+EXPLAIN
+SELECT * FROM t1
+WHERE a BETWEEN 4 AND 5 AND b IN (255,4) OR a IN (2,14,25) OR a!=2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index PRIMARY,idx idx 5 NULL 2 Using where; Using index
+SELECT * FROM t1
+WHERE a BETWEEN 4 AND 5 AND b IN (255,4) OR a IN (2,14,25) OR a!=2;
+a b
+167 9999
+168 10000
+DROP TABLE t1;
set session optimizer_switch='index_merge_sort_intersection=default';
SET SESSION STORAGE_ENGINE=DEFAULT;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 5a20057995d..71c1fafe4c0 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -3419,7 +3419,7 @@ SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr
FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using index condition; Using where
DROP TABLE t1,t2;
SET SQL_MODE='NO_UNSIGNED_SUBTRACTION';
CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
@@ -3457,7 +3457,7 @@ In next EXPLAIN, B.rows must be exactly 10:
explain select * from t2 A, t2 B where A.a=5 and A.b=5 and A.C<5
and B.a=5 and B.b=A.e and (B.b =1 or B.b = 3 or B.b=5);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE A range PRIMARY PRIMARY 12 NULL 4 Using where
+1 SIMPLE A range PRIMARY PRIMARY 12 NULL 4 Using index condition; Using where
1 SIMPLE B ref PRIMARY PRIMARY 8 const,test.A.e 10
drop table t1, t2;
CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX(b));
@@ -3471,12 +3471,12 @@ INSERT INTO t2 VALUES
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition
1 SIMPLE t2 ref c c 5 test.t1.a 2
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition; Using where
1 SIMPLE t2 ref c c 5 test.t1.a 2
DROP TABLE t1, t2;
create table t1 (
@@ -3566,19 +3566,19 @@ EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk < 'c' AND t2.pk=t1.fk;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 3 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 3 Using index condition; Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk BETWEEN 'a' AND 'b' AND t2.pk=t1.fk;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using index condition; Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk IN ('a','b') AND t2.pk=t1.fk;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using index condition; Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b varchar(20) NOT NULL, PRIMARY KEY(a));
@@ -3612,7 +3612,7 @@ WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t2 range si si 5 NULL 4 Using where
+1 SIMPLE t2 range si si 5 NULL 4 Using index condition; Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2,t3
@@ -3620,7 +3620,7 @@ WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee') ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t2 range si,ai si 5 NULL 4 Using where
+1 SIMPLE t2 range si,ai si 5 NULL 4 Using index condition; Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
@@ -3628,7 +3628,7 @@ WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t2 range si si 5 NULL 2 Using where
+1 SIMPLE t2 range si si 5 NULL 2 Using index condition; Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2,t3
@@ -3636,7 +3636,7 @@ WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t2 range si,ai si 5 NULL 2 Using where
+1 SIMPLE t2 range si,ai si 5 NULL 2 Using index condition; Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
DROP TABLE t1,t2,t3;
CREATE TABLE t1 ( f1 int primary key, f2 int, f3 int, f4 int, f5 int, f6 int, checked_out int);
@@ -3756,7 +3756,7 @@ AND t1.ts BETWEEN t2.dt1 AND t2.dt2
AND t1.ts BETWEEN "2006-01-01" AND "2006-12-31";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t1 range ts ts 4 NULL 1 Using where
+1 SIMPLE t1 range ts ts 4 NULL 1 Using index condition; Using where
SELECT * FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=30
AND t1.ts BETWEEN t2.dt1 AND t2.dt2
AND t1.ts BETWEEN "2006-01-01" AND "2006-12-31";
@@ -4382,12 +4382,12 @@ CREATE TABLE t1 (a INT KEY, b INT);
INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4);
EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND a = b LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using index condition; Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`b` = `test`.`t1`.`a`) and (`test`.`t1`.`a` > 1)) limit 2
EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND b = a LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using index condition; Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`b` = `test`.`t1`.`a`) and (`test`.`t1`.`a` > 1)) limit 2
DROP TABLE t1;
diff --git a/mysql-test/r/select_pkeycache.result b/mysql-test/r/select_pkeycache.result
index 5a20057995d..71c1fafe4c0 100644
--- a/mysql-test/r/select_pkeycache.result
+++ b/mysql-test/r/select_pkeycache.result
@@ -3419,7 +3419,7 @@ SELECT t2.sku, t2.sppr, t2.name, t1.sku, t1.pr
FROM t2, t1 WHERE t2.sku=20 AND (t2.sku=t1.sku OR t2.sppr=t1.sku);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 2 Using index condition; Using where
DROP TABLE t1,t2;
SET SQL_MODE='NO_UNSIGNED_SUBTRACTION';
CREATE TABLE t1 (i TINYINT UNSIGNED NOT NULL);
@@ -3457,7 +3457,7 @@ In next EXPLAIN, B.rows must be exactly 10:
explain select * from t2 A, t2 B where A.a=5 and A.b=5 and A.C<5
and B.a=5 and B.b=A.e and (B.b =1 or B.b = 3 or B.b=5);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE A range PRIMARY PRIMARY 12 NULL 4 Using where
+1 SIMPLE A range PRIMARY PRIMARY 12 NULL 4 Using index condition; Using where
1 SIMPLE B ref PRIMARY PRIMARY 8 const,test.A.e 10
drop table t1, t2;
CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX(b));
@@ -3471,12 +3471,12 @@ INSERT INTO t2 VALUES
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition
1 SIMPLE t2 ref c c 5 test.t1.a 2
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using where
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition; Using where
1 SIMPLE t2 ref c c 5 test.t1.a 2
DROP TABLE t1, t2;
create table t1 (
@@ -3566,19 +3566,19 @@ EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk < 'c' AND t2.pk=t1.fk;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 3 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 3 Using index condition; Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk BETWEEN 'a' AND 'b' AND t2.pk=t1.fk;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using index condition; Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
EXPLAIN SELECT t2.*
FROM t1 JOIN t2 ON t2.fk=t1.pk
WHERE t2.fk IN ('a','b') AND t2.pk=t1.fk;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 12 NULL 2 Using index condition; Using where
1 SIMPLE t2 eq_ref PRIMARY PRIMARY 18 test.t1.fk 1 Using where
DROP TABLE t1,t2;
CREATE TABLE t1 (a int, b varchar(20) NOT NULL, PRIMARY KEY(a));
@@ -3612,7 +3612,7 @@ WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t2 range si si 5 NULL 4 Using where
+1 SIMPLE t2 range si si 5 NULL 4 Using index condition; Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2,t3
@@ -3620,7 +3620,7 @@ WHERE t1.id = 8 AND t2.i BETWEEN t1.b AND t1.e AND
t3.a=t2.a AND t3.c IN ('bb','ee') ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t2 range si,ai si 5 NULL 4 Using where
+1 SIMPLE t2 range si,ai si 5 NULL 4 Using index condition; Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2 FORCE INDEX (si),t3
@@ -3628,7 +3628,7 @@ WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t2 range si si 5 NULL 2 Using where
+1 SIMPLE t2 range si si 5 NULL 2 Using index condition; Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
EXPLAIN
SELECT t3.a FROM t1,t2,t3
@@ -3636,7 +3636,7 @@ WHERE t1.id = 8 AND (t2.i=t1.b OR t2.i=t1.e) AND t3.a=t2.a AND
t3.c IN ('bb','ee');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t2 range si,ai si 5 NULL 2 Using where
+1 SIMPLE t2 range si,ai si 5 NULL 2 Using index condition; Using where
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
DROP TABLE t1,t2,t3;
CREATE TABLE t1 ( f1 int primary key, f2 int, f3 int, f4 int, f5 int, f6 int, checked_out int);
@@ -3756,7 +3756,7 @@ AND t1.ts BETWEEN t2.dt1 AND t2.dt2
AND t1.ts BETWEEN "2006-01-01" AND "2006-12-31";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
-1 SIMPLE t1 range ts ts 4 NULL 1 Using where
+1 SIMPLE t1 range ts ts 4 NULL 1 Using index condition; Using where
SELECT * FROM t1 LEFT JOIN t2 ON (t1.a=t2.a) WHERE t1.a=30
AND t1.ts BETWEEN t2.dt1 AND t2.dt2
AND t1.ts BETWEEN "2006-01-01" AND "2006-12-31";
@@ -4382,12 +4382,12 @@ CREATE TABLE t1 (a INT KEY, b INT);
INSERT INTO t1 VALUES (1,1), (2,2), (3,3), (4,4);
EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND a = b LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using index condition; Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`b` = `test`.`t1`.`a`) and (`test`.`t1`.`a` > 1)) limit 2
EXPLAIN EXTENDED SELECT a, b FROM t1 WHERE a > 1 AND b = a LIMIT 2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using where
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 100.00 Using index condition; Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`b` = `test`.`t1`.`a`) and (`test`.`t1`.`a` > 1)) limit 2
DROP TABLE t1;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 82b8e740cdc..6acea0d1680 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -2969,9 +2969,10 @@ Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cac
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 10 func,func 1 100.00
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`two` = `test`.`t1`.`two`) and (`test`.`t2`.`one` = `test`.`t1`.`one`) and (`test`.`t2`.`flag` = 'N'))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`flag` = 'N'))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -3558,7 +3559,8 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
a b
@@ -3568,8 +3570,9 @@ AAA 8
EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 index NULL a 8 NULL 1
+1 PRIMARY t1 ALL a NULL NULL NULL 9 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
DROP TABLE t1;
create table t1( f1 int,f2 int);
insert into t1 values (1,1),(2,2);
@@ -4512,15 +4515,17 @@ INSERT INTO t1 VALUES (1),(2);
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
+1 PRIMARY <subquery2> const distinct_key distinct_key 4 const 1 100.00
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <expr_cache><1>(<in_optimizer>(1,<exists>(select 1 from `test`.`t1` group by `test`.`t1`.`a` having (1 = <ref_null_helper>(1)))))
+Note 1003 select 1 AS `1` from <materialize> (select 1 from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where (`<subquery2>`.`1` = 1)
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
+1 PRIMARY <subquery2> const distinct_key distinct_key 4 const 1 100.00
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <expr_cache><1>(<in_optimizer>(1,<exists>(select 1 from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` having (1 = <ref_null_helper>(1)))))
+Note 1003 select 1 AS `1` from <materialize> (select 1 from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a`) join `test`.`t1` where (`<subquery2>`.`1` = 1)
DROP TABLE t1;
#
# Bug#45061: Incorrectly market field caused wrong result.
@@ -5548,10 +5553,11 @@ explain SELECT * FROM ot1,ot4
WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 2 Start temporary
-1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
-1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; End temporary; Using join buffer (flat, BNL join)
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 2
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 24 Using where
+1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY it2 ALL NULL NULL NULL NULL 4
+2 SUBQUERY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
#
# Bug#729039: NULL keys used to evaluate subquery
@@ -6016,4 +6022,14 @@ ERROR 21000: Subquery returns more than 1 row
SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+#
+# LP BUG#833777 Performance regression with deeply nested subqueries
+#
+create table t1 (a int not null, b char(10) not null);
+insert into t1 values (1, 'a');
+set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
+select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1)))))))))))))))))))))))))))));
+a
+1
+drop table t1;
set optimizer_switch=@subselect_tmp;
diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result
index 501804a0006..41f1a842a90 100644
--- a/mysql-test/r/subselect3.result
+++ b/mysql-test/r/subselect3.result
@@ -975,7 +975,7 @@ i1 i2
# Baseline:
SHOW STATUS LIKE '%Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 17
+Handler_read_rnd_next 18
INSERT INTO t1 VALUES (NULL, NULL);
FLUSH STATUS;
@@ -992,7 +992,7 @@ i1 i2
# (read record from t1, but do not read from t2)
SHOW STATUS LIKE '%Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 18
+Handler_read_rnd_next 19
set @@optimizer_switch=@save_optimizer_switch2;
DROP TABLE t1,t2;
End of 5.1 tests
@@ -1023,6 +1023,8 @@ create table t11 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) orde
create table t12 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 desc;
create table t21 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 asc;
create table t22 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
+set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch='materialization=off';
update t22 set c = '2005-12-08 15:58:27' where a = 255;
explain select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
@@ -1035,10 +1037,11 @@ select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
a b c
256 67 NULL
+set @@optimizer_switch=@save_optimizer_switch;
drop table t1, t11, t12, t21, t22;
create table t1(a int);
insert into t1 values (0),(1);
-set @@optimizer_switch='firstmatch=off';
+set @@optimizer_switch='firstmatch=off,materialization=off';
explain
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
id select_type table type possible_keys key key_len ref rows Extra
@@ -1112,6 +1115,8 @@ a
18
19
set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch='materialization=off';
explain select * from (select a from t0) X where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11
@@ -1134,10 +1139,11 @@ insert into t4 select a from t3;
explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
and t4.pk=t1.c);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; LooseScan
+1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using index condition; Using where; LooseScan
1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 Using index; FirstMatch(t1)
1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
drop table t1, t3, t4;
+set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int) as select * from t0 where a < 5;
set @save_max_heap_table_size=@@max_heap_table_size;
set @@optimizer_switch='firstmatch=off,materialization=off';
@@ -1167,8 +1173,9 @@ create table t3 ( a int , filler char(100), key(a));
insert into t3 select A.a + 10*B.a, 'filler' from t0 A, t0 B;
explain select * from t3 where a in (select a from t2) and (a > 5 or a < 10);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary
-1 PRIMARY t3 ref a a 5 test.t2.a 1 End temporary
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
+1 PRIMARY t3 ref a a 5 test.t2.a 1
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
select * from t3 where a in (select a from t2);
a filler
1 filler
@@ -1207,6 +1214,8 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where; End temporary; Using join buffer (flat, BNL join)
drop table t1;
set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch='materialization=off';
create table t1 (a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t2 as select * from t1;
@@ -1267,11 +1276,12 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 range a a 5 NULL 8 Using where; Using index; LooseScan
1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
drop table t1,t2;
+set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int, b int);
insert into t1 select a,a from t0;
create table t2 (a int, b int);
insert into t2 select A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B;
-set @@optimizer_switch='firstmatch=off';
+set @@optimizer_switch='firstmatch=off,materialization=off';
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Start temporary
@@ -1287,6 +1297,7 @@ id select_type table type possible_keys key key_len ref rows Extra
set @@optimizer_search_depth=@save_optimizer_search_depth;
set @@optimizer_switch=@save_optimizer_switch;
drop table t0, t1, t2;
+set @@optimizer_switch='materialization=off';
create table t0 (a decimal(4,2));
insert into t0 values (10.24), (22.11);
create table t1 as select * from t0;
@@ -1325,6 +1336,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
drop table t0,t1,t2;
+set @@optimizer_switch=@save_optimizer_switch;
BUG#37842: Assertion in DsMrr_impl::dsmrr_init, at handler.cc:4307
@@ -1386,6 +1398,8 @@ postalStripped varchar(100)
);
insert into t3 values (1,1, 'foo'), (2,2,'bar');
The following must be converted to a semi-join:
+set @save_optimizer_switch=@@optimizer_switch;
+set @@optimizer_switch='materialization=off';
explain extended SELECT a.idIndividual FROM t1 a
WHERE a.idIndividual IN
( SELECT c.idObj FROM t3 cona
@@ -1398,6 +1412,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY a eq_ref PRIMARY PRIMARY 4 test.c.idObj 1 100.00 Using index; End temporary
Warnings:
Note 1003 select `test`.`a`.`idIndividual` AS `idIndividual` from `test`.`t1` `a` semi join (`test`.`t3` `cona` join `test`.`t2` `c`) where ((`test`.`c`.`idContact` = `test`.`cona`.`idContact`) and (`test`.`a`.`idIndividual` = `test`.`c`.`idObj`) and (`test`.`cona`.`postalStripped` = 'T2H3B2'))
+set @@optimizer_switch=@save_optimizer_switch;
drop table t1,t2,t3;
#
# BUG#47367 Crash in Name_resolution_context::process_error
diff --git a/mysql-test/r/subselect3_jcl6.result b/mysql-test/r/subselect3_jcl6.result
index 645e3a1d84e..7cf3e2c5e9e 100644
--- a/mysql-test/r/subselect3_jcl6.result
+++ b/mysql-test/r/subselect3_jcl6.result
@@ -984,7 +984,7 @@ i1 i2
# Baseline:
SHOW STATUS LIKE '%Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 17
+Handler_read_rnd_next 18
INSERT INTO t1 VALUES (NULL, NULL);
FLUSH STATUS;
@@ -1001,7 +1001,7 @@ i1 i2
# (read record from t1, but do not read from t2)
SHOW STATUS LIKE '%Handler_read_rnd_next';
Variable_name Value
-Handler_read_rnd_next 18
+Handler_read_rnd_next 19
set @@optimizer_switch=@save_optimizer_switch2;
DROP TABLE t1,t2;
End of 5.1 tests
@@ -1032,6 +1032,8 @@ create table t11 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) orde
create table t12 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) order by 3 desc;
create table t21 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 asc;
create table t22 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
+set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch='materialization=off';
update t22 set c = '2005-12-08 15:58:27' where a = 255;
explain select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
@@ -1044,10 +1046,11 @@ select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
a b c
256 67 NULL
+set @@optimizer_switch=@save_optimizer_switch;
drop table t1, t11, t12, t21, t22;
create table t1(a int);
insert into t1 values (0),(1);
-set @@optimizer_switch='firstmatch=off';
+set @@optimizer_switch='firstmatch=off,materialization=off';
explain
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
id select_type table type possible_keys key key_len ref rows Extra
@@ -1121,6 +1124,8 @@ a
18
19
set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch='materialization=off';
explain select * from (select a from t0) X where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11
@@ -1147,6 +1152,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t4 eq_ref PRIMARY PRIMARY 4 test.t1.c 1 Using index; FirstMatch(t1)
1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
drop table t1, t3, t4;
+set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int) as select * from t0 where a < 5;
set @save_max_heap_table_size=@@max_heap_table_size;
set @@optimizer_switch='firstmatch=off,materialization=off';
@@ -1176,8 +1182,9 @@ create table t3 ( a int , filler char(100), key(a));
insert into t3 select A.a + 10*B.a, 'filler' from t0 A, t0 B;
explain select * from t3 where a in (select a from t2) and (a > 5 or a < 10);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary
-1 PRIMARY t3 ref a a 5 test.t2.a 1 End temporary; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
+1 PRIMARY t3 ref a a 5 test.t2.a 1 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
select * from t3 where a in (select a from t2);
a filler
1 filler
@@ -1216,6 +1223,8 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 hash_ALL NULL #hash#$hj 6 test.t1.a 2 Using where; End temporary; Using join buffer (flat, BNLH join)
drop table t1;
set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch='materialization=off';
create table t1 (a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t2 as select * from t1;
@@ -1276,11 +1285,12 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 range a a 5 NULL 8 Using where; Using index; LooseScan
1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
drop table t1,t2;
+set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int, b int);
insert into t1 select a,a from t0;
create table t2 (a int, b int);
insert into t2 select A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B;
-set @@optimizer_switch='firstmatch=off';
+set @@optimizer_switch='firstmatch=off,materialization=off';
explain select * from t1 where (a,b) in (select a,b from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where; Start temporary
@@ -1296,6 +1306,7 @@ id select_type table type possible_keys key key_len ref rows Extra
set @@optimizer_search_depth=@save_optimizer_search_depth;
set @@optimizer_switch=@save_optimizer_switch;
drop table t0, t1, t2;
+set @@optimizer_switch='materialization=off';
create table t0 (a decimal(4,2));
insert into t0 values (10.24), (22.11);
create table t1 as select * from t0;
@@ -1334,6 +1345,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY Y hash_ALL NULL #hash#$hj 5 test.t1.b 6 Using where; Using join buffer (incremental, BNLH join)
1 PRIMARY Z hash_ALL NULL #hash#$hj 5 test.t1.c 6 Using where; End temporary; Using join buffer (incremental, BNLH join)
drop table t0,t1,t2;
+set @@optimizer_switch=@save_optimizer_switch;
BUG#37842: Assertion in DsMrr_impl::dsmrr_init, at handler.cc:4307
@@ -1395,6 +1407,8 @@ postalStripped varchar(100)
);
insert into t3 values (1,1, 'foo'), (2,2,'bar');
The following must be converted to a semi-join:
+set @save_optimizer_switch=@@optimizer_switch;
+set @@optimizer_switch='materialization=off';
explain extended SELECT a.idIndividual FROM t1 a
WHERE a.idIndividual IN
( SELECT c.idObj FROM t3 cona
@@ -1407,6 +1421,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY a eq_ref PRIMARY PRIMARY 4 test.c.idObj 1 100.00 Using index; End temporary
Warnings:
Note 1003 select `test`.`a`.`idIndividual` AS `idIndividual` from `test`.`t1` `a` semi join (`test`.`t3` `cona` join `test`.`t2` `c`) where ((`test`.`c`.`idContact` = `test`.`cona`.`idContact`) and (`test`.`a`.`idIndividual` = `test`.`c`.`idObj`) and (`test`.`cona`.`postalStripped` = 'T2H3B2'))
+set @@optimizer_switch=@save_optimizer_switch;
drop table t1,t2,t3;
#
# BUG#47367 Crash in Name_resolution_context::process_error
diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result
index 9c81a0f552d..24ed46a9068 100644
--- a/mysql-test/r/subselect4.result
+++ b/mysql-test/r/subselect4.result
@@ -119,6 +119,8 @@ CREATE TABLE t4 ( a INT );
INSERT INTO t4 VALUES (1), (2), (3);
CREATE TABLE t5 ( a INT );
INSERT INTO t5 VALUES (NULL), (2);
+SET @old_optimizer_switch = @@session.optimizer_switch;
+SET SESSION optimizer_switch = 'materialization=off,in_to_exists=on,semijoin=off';
EXPLAIN
SELECT * FROM t1 WHERE ( a, b ) NOT IN ( SELECT c, d FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
@@ -190,6 +192,7 @@ SELECT * FROM t1 WHERE NULL NOT IN ( SELECT c FROM t2 WHERE c = 1 AND c <> 1 );
a b
1 NULL
2 NULL
+SET SESSION optimizer_switch = @old_optimizer_switch;
DROP TABLE t1, t2, t3, t4, t5;
#
# Bug#58207: invalid memory reads when using default column value and
@@ -1092,17 +1095,19 @@ EXPLAIN
SELECT * FROM (t2 LEFT JOIN t1 ON t1.c1) LEFT JOIN t3 on t3.c1 WHERE 's' IN (SELECT c1 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
SELECT * FROM (t2 LEFT JOIN t1 ON t1.c1) LEFT JOIN t3 on t3.c1 WHERE 's' IN (SELECT c1 FROM t2);
c1 c1 c1
EXPLAIN
SELECT * FROM t4 LEFT JOIN t2 ON t4.c1 WHERE 's' IN (SELECT c1 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Start temporary; End temporary
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
1 PRIMARY t4 index NULL PRIMARY 3 NULL 2 Using index; Using join buffer (flat, BNL join)
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
SELECT * FROM t4 LEFT JOIN t2 ON t4.c1 WHERE 's' IN (SELECT c1 FROM t2);
c1 c1
drop table t1, t2, t3, t4;
diff --git a/mysql-test/r/subselect_cache.result b/mysql-test/r/subselect_cache.result
index 9b515ba8e52..4b0b4c0ead8 100644
--- a/mysql-test/r/subselect_cache.result
+++ b/mysql-test/r/subselect_cache.result
@@ -1356,12 +1356,12 @@ Subquery_cache_miss 0
show status like '%Handler_read%';
Variable_name Value
Handler_read_first 0
-Handler_read_key 0
+Handler_read_key 11
Handler_read_last 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
-Handler_read_rnd_next 188
+Handler_read_rnd_next 145
set optimizer_switch='subquery_cache=on';
flush status;
select a, b , exists (select * from t2 where b=d) as SUBSE, b in (select d from t2) as SUBSI, (select d from t2 where b=c) SUBSR from t1;
@@ -1385,12 +1385,12 @@ Subquery_cache_miss 18
show status like '%Handler_read%';
Variable_name Value
Handler_read_first 0
-Handler_read_key 27
+Handler_read_key 32
Handler_read_last 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
-Handler_read_rnd_next 102
+Handler_read_rnd_next 84
#several subqueries (several levels)
set optimizer_switch='subquery_cache=off';
flush status;
diff --git a/mysql-test/r/subselect_extra.result b/mysql-test/r/subselect_extra.result
index bb2ae830c20..72362415b2b 100644
--- a/mysql-test/r/subselect_extra.result
+++ b/mysql-test/r/subselect_extra.result
@@ -307,7 +307,8 @@ EXPLAIN SELECT 1 FROM t1 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index PRIMARY,i2 PRIMARY 4 NULL 144 Using index
-1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Using where; FirstMatch(t1); Using join buffer (flat, BNL join)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 144
CREATE TABLE t2 (a INT, b INT, KEY(a));
INSERT INTO t2 VALUES (1, 1), (2, 2), (3,3), (4,4);
EXPLAIN SELECT a, SUM(b) FROM t2 GROUP BY a LIMIT 2;
diff --git a/mysql-test/r/subselect_extra_no_semijoin.result b/mysql-test/r/subselect_extra_no_semijoin.result
index 78d122cfcd4..5d592541e8b 100644
--- a/mysql-test/r/subselect_extra_no_semijoin.result
+++ b/mysql-test/r/subselect_extra_no_semijoin.result
@@ -311,7 +311,7 @@ EXPLAIN SELECT 1 FROM t1 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 144 Using where; Using index
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 144 Using where
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 144
CREATE TABLE t2 (a INT, b INT, KEY(a));
INSERT INTO t2 VALUES (1, 1), (2, 2), (3,3), (4,4);
EXPLAIN SELECT a, SUM(b) FROM t2 GROUP BY a LIMIT 2;
@@ -324,7 +324,7 @@ EXPLAIN SELECT 1 FROM t2 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a 5 NULL 4 Using where; Using index
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 144 Using where
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 144
DROP TABLE t1, t2;
#
# From derived_view.test
@@ -349,9 +349,9 @@ WHERE t.a IN (SELECT b FROM t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
-3 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 100.00
+3 SUBQUERY t1 system NULL NULL NULL NULL 1 100.00
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from dual where (<cache>(0) = 0))))
+Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,0 in ( <materialize> (select 0 from dual ), <primary_index_lookup>(0 in <temporary table> on distinct_key where ((0 = `<subquery3>`.`b`))))))
SELECT * FROM t2 RIGHT JOIN v1 AS t ON t.a != 0
WHERE t.a IN (SELECT b FROM t1);
a a b
@@ -362,9 +362,9 @@ WHERE t.a IN (SELECT b FROM t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
-2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 100.00
+2 SUBQUERY t1 system NULL NULL NULL NULL 1 100.00
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,<exists>(select 0 from dual where (<cache>(0) = 0))))
+Note 1003 select `test`.`t2`.`a` AS `a`,0 AS `a`,0 AS `b` from `test`.`t2` where <expr_cache><0>(<in_optimizer>(0,0 in ( <materialize> (select 0 from dual ), <primary_index_lookup>(0 in <temporary table> on distinct_key where ((0 = `<subquery2>`.`b`))))))
DROP VIEW v1;
DROP TABLE t1,t2;
#
diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result
index d155a2cd3a8..499963710e1 100644
--- a/mysql-test/r/subselect_mat.result
+++ b/mysql-test/r/subselect_mat.result
@@ -1847,7 +1847,7 @@ EXPLAIN SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
-2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 2 Using where
+2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 2 Using index condition
SELECT pk FROM t1 WHERE (a) IN (SELECT a FROM t2 WHERE pk > 0);
pk
2
diff --git a/mysql-test/r/subselect_mat_cost_bugs.result b/mysql-test/r/subselect_mat_cost_bugs.result
index 2f5d799a44d..9ba318a58f1 100644
--- a/mysql-test/r/subselect_mat_cost_bugs.result
+++ b/mysql-test/r/subselect_mat_cost_bugs.result
@@ -301,7 +301,7 @@ insert into t2 values (0,0,0,'filler'),(0,1,1,'filler'),(0,2,2,'filler'),(0,3,3,
create index key1 on t2 (kp1, kp2);
create index key2 on t2 (kp1);
create index key3 on t2 (kp2);
-set session optimizer_switch='default';
+SET @@optimizer_switch='materialization=off,semijoin=off,in_to_exists=on';
analyze table t2;
Table Op Msg_type Msg_text
test.t2 analyze status OK
@@ -312,6 +312,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t2 index_subquery key1,key2,key3 key1 10 func,const 1 Using where
select c1 from t1 where c1 in (select kp1 from t2 where kp2 = 10 and c2 = 4) or c1 > 7;
c1
+set @@optimizer_switch='default';
drop table t1, t2;
#
# LP BUG#800679: Assertion `outer_join->table_count > 0' failed in
@@ -355,8 +356,8 @@ WHERE t4.a >= t3.b
AND a = SOME (SELECT b FROM t5));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY t5 index c c 10 NULL 2 Using where; Using index; LooseScan
-2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t5.b 1 Using where
+2 DEPENDENT SUBQUERY t5 index c c 10 NULL 2 Using where; Using index; Start temporary
+2 DEPENDENT SUBQUERY t4 eq_ref PRIMARY PRIMARY 4 test.t5.b 1 Using index condition; Using where; End temporary
SELECT *
FROM t3
WHERE t3.b > ALL (
diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result
index 0bddfb5f477..4b3dce76f0a 100644
--- a/mysql-test/r/subselect_no_mat.result
+++ b/mysql-test/r/subselect_no_mat.result
@@ -1,6 +1,6 @@
select @@optimizer_switch like '%materialization=on%';
@@optimizer_switch like '%materialization=on%'
-0
+1
set optimizer_switch='materialization=off';
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
@@ -6021,8 +6021,18 @@ ERROR 21000: Subquery returns more than 1 row
SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+#
+# LP BUG#833777 Performance regression with deeply nested subqueries
+#
+create table t1 (a int not null, b char(10) not null);
+insert into t1 values (1, 'a');
+set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
+select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1)))))))))))))))))))))))))))));
+a
+1
+drop table t1;
set optimizer_switch=@subselect_tmp;
set optimizer_switch=default;
select @@optimizer_switch like '%materialization=on%';
@@optimizer_switch like '%materialization=on%'
-0
+1
diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result
index af0fc163f80..37166b3a537 100644
--- a/mysql-test/r/subselect_no_opts.result
+++ b/mysql-test/r/subselect_no_opts.result
@@ -6017,5 +6017,15 @@ ERROR 21000: Subquery returns more than 1 row
SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+#
+# LP BUG#833777 Performance regression with deeply nested subqueries
+#
+create table t1 (a int not null, b char(10) not null);
+insert into t1 values (1, 'a');
+set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
+select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1)))))))))))))))))))))))))))));
+a
+1
+drop table t1;
set optimizer_switch=@subselect_tmp;
set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result
index febb522254c..dd5a4623419 100644
--- a/mysql-test/r/subselect_no_scache.result
+++ b/mysql-test/r/subselect_no_scache.result
@@ -2973,9 +2973,10 @@ Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<in_optim
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 10 func,func 1 100.00
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`two` = `test`.`t1`.`two`) and (`test`.`t2`.`one` = `test`.`t1`.`one`) and (`test`.`t2`.`flag` = 'N'))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`flag` = 'N'))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -3562,7 +3563,8 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
a b
@@ -3572,8 +3574,9 @@ AAA 8
EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 index NULL a 8 NULL 1
+1 PRIMARY t1 ALL a NULL NULL NULL 9 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
DROP TABLE t1;
create table t1( f1 int,f2 int);
insert into t1 values (1,1),(2,2);
@@ -4516,15 +4519,17 @@ INSERT INTO t1 VALUES (1),(2);
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
+1 PRIMARY <subquery2> const distinct_key distinct_key 4 const 1 100.00
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,<exists>(select 1 from `test`.`t1` group by `test`.`t1`.`a` having (1 = <ref_null_helper>(1))))
+Note 1003 select 1 AS `1` from <materialize> (select 1 from `test`.`t1` group by `test`.`t1`.`a`) join `test`.`t1` where (`<subquery2>`.`1` = 1)
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
+1 PRIMARY <subquery2> const distinct_key distinct_key 4 const 1 100.00
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,<exists>(select 1 from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` having (1 = <ref_null_helper>(1))))
+Note 1003 select 1 AS `1` from <materialize> (select 1 from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a`) join `test`.`t1` where (`<subquery2>`.`1` = 1)
DROP TABLE t1;
#
# Bug#45061: Incorrectly market field caused wrong result.
@@ -5552,10 +5557,11 @@ explain SELECT * FROM ot1,ot4
WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 2 Start temporary
-1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
-1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; End temporary; Using join buffer (flat, BNL join)
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 2
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 24 Using where
+1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY it2 ALL NULL NULL NULL NULL 4
+2 SUBQUERY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
#
# Bug#729039: NULL keys used to evaluate subquery
@@ -6020,6 +6026,16 @@ ERROR 21000: Subquery returns more than 1 row
SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+#
+# LP BUG#833777 Performance regression with deeply nested subqueries
+#
+create table t1 (a int not null, b char(10) not null);
+insert into t1 values (1, 'a');
+set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
+select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1)))))))))))))))))))))))))))));
+a
+1
+drop table t1;
set optimizer_switch=@subselect_tmp;
set optimizer_switch=default;
select @@optimizer_switch like '%subquery_cache=on%';
diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result
index 5130442b56d..dda350592b7 100644
--- a/mysql-test/r/subselect_no_semijoin.result
+++ b/mysql-test/r/subselect_no_semijoin.result
@@ -904,9 +904,9 @@ a t1.a in (select t2.a from t2)
explain extended SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
+2 SUBQUERY t2 index a a 5 NULL 3 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having <is_not_null_test>(`test`.`t2`.`a`))))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `<subquery2>`.`a`)))))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -918,10 +918,10 @@ a t1.a in (select t2.a from t2,t3 where t3.a=t2.a)
explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
-2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY t2 index a a 5 NULL 3 100.00 Using index
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,<exists>(select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 select `test`.`t1`.`a` AS `a`,<expr_cache><`test`.`t1`.`a`>(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where (`test`.`t3`.`a` = `test`.`t2`.`a`) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `<subquery2>`.`a`)))))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
# check correct NULL Processing for normal IN/ALL/ANY
# and 2 ways of max/min optimization
@@ -1434,9 +1434,9 @@ a
explain extended select * from t2 where t2.a in (select a from t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index
+2 SUBQUERY t1 index PRIMARY PRIMARY 4 NULL 4 100.00 Using index
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `<subquery2>`.`a`))))))
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
a
2
@@ -1444,9 +1444,9 @@ a
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using where
+2 SUBQUERY t1 ALL PRIMARY NULL NULL NULL 4 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(<primary_index_lookup>(<cache>(`test`.`t2`.`a`) in t1 on PRIMARY where ((`test`.`t1`.`b` <> 30) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` from `test`.`t1` where (`test`.`t1`.`b` <> 30) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `<subquery2>`.`a`))))))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
a
2
@@ -1454,10 +1454,10 @@ a
explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 func 1 100.00 Using where
-2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 100.00 Using index
+2 SUBQUERY t3 index PRIMARY PRIMARY 4 NULL 3 100.00 Using index
+2 SUBQUERY t1 ALL PRIMARY NULL NULL NULL 4 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,<exists>(select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t1`.`b`) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))))
+Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <expr_cache><`test`.`t2`.`a`>(<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (select `test`.`t1`.`a` from `test`.`t1` join `test`.`t3` where (`test`.`t1`.`b` = `test`.`t3`.`a`) ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `<subquery2>`.`a`))))))
drop table t1, t2, t3;
create table t1 (a int, b int, index a (a,b));
create table t2 (a int, index a (a));
@@ -1605,27 +1605,27 @@ a3 1
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index s1 s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,(not(<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(<is_not_null_test>(`test`.`t2`.`s1`)))))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 select `test`.`t1`.`s1` AS `s1`,(not(<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `<subquery2>`.`s1`)))))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index s1 s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(<is_not_null_test>(`test`.`t2`.`s1`)))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 select `test`.`t1`.`s1` AS `s1`,<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `<subquery2>`.`s1`)))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index s1 s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,(not(<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond(<is_not_null_test>(`test`.`t2`.`s1`)))))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 select `test`.`t1`.`s1` AS `s1`,(not(<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `<subquery2>`.`s1`)))))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
+2 SUBQUERY t2 index s1 s1 6 NULL 2 50.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1`.`s1` AS `s1`,(not(<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < 'a2') having trigcond(<is_not_null_test>(`test`.`t2`.`s1`)))))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 select `test`.`t1`.`s1` AS `s1`,(not(<expr_cache><`test`.`t1`.`s1`>(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (select `test`.`t2`.`s1` from `test`.`t2` where (`test`.`t2`.`s1` < 'a2') ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `<subquery2>`.`s1`)))))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int not null);
create table t3 (a int);
@@ -1878,9 +1878,9 @@ id text
explain extended select * from t1 where id not in (select id from t1 where id < 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
+2 SUBQUERY t1 range PRIMARY PRIMARY 4 NULL 7 100.00 Using where; Using index
Warnings:
-Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where ((`test`.`t1`.`id` < 8) and (<cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`))))))))
+Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<expr_cache><`test`.`t1`.`id`>(<in_optimizer>(`test`.`t1`.`id`,`test`.`t1`.`id` in ( <materialize> (select `test`.`t1`.`id` from `test`.`t1` where (`test`.`t1`.`id` < 8) ), <primary_index_lookup>(`test`.`t1`.`id` in <temporary table> on distinct_key where ((`test`.`t1`.`id` = `<subquery2>`.`id`))))))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
@@ -2964,21 +2964,21 @@ one two test
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0') as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where ((`test`.`t2`.`flag` = '0') and trigcond(((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond(((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)))) having (trigcond(<is_not_null_test>(`test`.`t2`.`one`)) and trigcond(<is_not_null_test>(`test`.`t2`.`two`)))))) AS `test` from `test`.`t1`
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where (`test`.`t2`.`flag` = '0') ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where ((`test`.`t1`.`one` = `<subquery2>`.`one`) and (`test`.`t1`.`two` = `<subquery2>`.`two`)))))) AS `test` from `test`.`t1`
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00 Using where
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where ((`test`.`t2`.`flag` = 'N') and (<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) and (<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`)))))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where <expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where (`test`.`t2`.`flag` = 'N') ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where ((`test`.`t1`.`one` = `<subquery2>`.`one`) and (`test`.`t1`.`two` = `<subquery2>`.`two`))))))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
-2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; Using temporary
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; Using temporary
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),<exists>(select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where (`test`.`t2`.`flag` = '0') group by `test`.`t2`.`one`,`test`.`t2`.`two` having (trigcond(((<cache>(`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond(((<cache>(`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`))) and trigcond(<is_not_null_test>(`test`.`t2`.`one`)) and trigcond(<is_not_null_test>(`test`.`t2`.`two`)))))) AS `test` from `test`.`t1`
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cache><`test`.`t1`.`one`,`test`.`t1`.`two`>(<in_optimizer>((`test`.`t1`.`one`,`test`.`t1`.`two`),(`test`.`t1`.`one`,`test`.`t1`.`two`) in ( <materialize> (select `test`.`t2`.`one`,`test`.`t2`.`two` from `test`.`t2` where (`test`.`t2`.`flag` = '0') group by `test`.`t2`.`one`,`test`.`t2`.`two` ), <primary_index_lookup>(`test`.`t1`.`one` in <temporary table> on distinct_key where ((`test`.`t1`.`one` = `<subquery2>`.`one`) and (`test`.`t1`.`two` = `<subquery2>`.`two`)))))) AS `test` from `test`.`t1`
DROP TABLE t1,t2;
set optimizer_switch=@tmp11867_optimizer_switch;
CREATE TABLE t1 (a char(5), b char(5));
@@ -3159,7 +3159,7 @@ INSERT INTO t2 VALUES (1),(2),(3);
EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 3
-2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using index; Full scan on NULL key
+2 SUBQUERY t1 index a a 5 NULL 5 Using index
SELECT a, a IN (SELECT a FROM t1) FROM t2;
a a IN (SELECT a FROM t1)
1 1
@@ -3559,7 +3559,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
a b
@@ -3570,7 +3570,7 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 index NULL a 8 NULL 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
DROP TABLE t1;
create table t1( f1 int,f2 int);
insert into t1 values (1,1),(2,2);
@@ -4364,7 +4364,7 @@ CREATE INDEX I2 ON t1 (b);
EXPLAIN SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY t1 index_subquery I1 I1 2 func 2 Using index; Using where
+2 SUBQUERY t1 index I1 I1 2 NULL 2 Using index
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1);
a b
CREATE TABLE t2 (a VARCHAR(1), b VARCHAR(10));
@@ -4374,14 +4374,14 @@ CREATE INDEX I2 ON t2 (b);
EXPLAIN SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY t2 index_subquery I1 I1 4 func 2 Using index; Using where
+2 SUBQUERY t2 index I1 I1 4 NULL 2 Using index
SELECT a,b FROM t2 WHERE b IN (SELECT a FROM t2);
a b
EXPLAIN
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY t1 index_subquery I1 I1 2 func 2 Using index; Using where
+2 SUBQUERY t1 index I1 I1 2 NULL 2 Using where; Using index
SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500);
a b
DROP TABLE t1,t2;
@@ -4513,15 +4513,15 @@ INSERT INTO t1 VALUES (1),(2);
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <expr_cache><1>(<in_optimizer>(1,<exists>(select 1 from `test`.`t1` group by `test`.`t1`.`a` having (1 = <ref_null_helper>(1)))))
+Note 1003 select 1 AS `1` from `test`.`t1` where <expr_cache><1>(<in_optimizer>(1,1 in ( <materialize> (select 1 from `test`.`t1` group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `<subquery2>`.`1`))))))
EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where; Using temporary
Warnings:
-Note 1003 select 1 AS `1` from `test`.`t1` where <expr_cache><1>(<in_optimizer>(1,<exists>(select 1 from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` having (1 = <ref_null_helper>(1)))))
+Note 1003 select 1 AS `1` from `test`.`t1` where <expr_cache><1>(<in_optimizer>(1,1 in ( <materialize> (select 1 from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` ), <primary_index_lookup>(1 in <temporary table> on distinct_key where ((1 = `<subquery2>`.`1`))))))
DROP TABLE t1;
#
# Bug#45061: Incorrectly market field caused wrong result.
@@ -4587,7 +4587,7 @@ WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
ORDER BY outr.pk;
id select_type table type possible_keys key key_len ref rows Extra
x x outr ALL x x x x x x
-x x t1 eq_ref x x x x x x
+x x t1 index x x x x x x
x x t2 index x x x x x x
# should not crash on debug binaries
SELECT * FROM t2 outr
@@ -5551,8 +5551,8 @@ FROM it2,it3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot1 ALL NULL NULL NULL NULL 2
1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
-2 DEPENDENT SUBQUERY it2 ALL NULL NULL NULL NULL 4 Using where
-2 DEPENDENT SUBQUERY it3 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY it2 ALL NULL NULL NULL NULL 4
+2 SUBQUERY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
#
# Bug#729039: NULL keys used to evaluate subquery
@@ -5596,8 +5596,8 @@ INSERT INTO t2 VALUES (15,4);
EXPLAIN SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using index
-2 DEPENDENT SUBQUERY it eq_ref PRIMARY PRIMARY 4 func 1 Using index
+2 SUBQUERY t2 index NULL PRIMARY 4 NULL 3 Using index
+2 SUBQUERY it index PRIMARY PRIMARY 4 NULL 3 Using index; Using join buffer (flat, BNL join)
SELECT * FROM t1 WHERE pk IN (SELECT it.pk FROM t2 JOIN t2 AS it ON 1);
pk i
11 0
@@ -5840,7 +5840,7 @@ WHERE (t2.b , t1.c) NOT IN (SELECT * from t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 Using where
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 2
SELECT t2.b , t1.c
FROM t2 LEFT JOIN t1 ON t1.c < 3
WHERE (t2.b, t1.c) NOT IN (SELECT * from t3);
@@ -6017,5 +6017,15 @@ ERROR 21000: Subquery returns more than 1 row
SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+#
+# LP BUG#833777 Performance regression with deeply nested subqueries
+#
+create table t1 (a int not null, b char(10) not null);
+insert into t1 values (1, 'a');
+set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
+select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1)))))))))))))))))))))))))))));
+a
+1
+drop table t1;
set optimizer_switch=@subselect_tmp;
set @optimizer_switch_for_subselect_test=null;
diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result
index 42f8f3ca009..af29a0332f3 100644
--- a/mysql-test/r/subselect_sj.result
+++ b/mysql-test/r/subselect_sj.result
@@ -79,18 +79,18 @@ id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY A ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY B ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t10 unique_suBquery PRIMARY PRIMARY 4 func 1 100.00 Using index
+2 SUBQUERY t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on((<in_optimizer>(`test`.`B`.`A`,<exists>(<primAry_index_lookup>(<cAche>(`test`.`B`.`A`) in t10 on PRIMARY))) And (`test`.`A`.`A` = `test`.`t1`.`A`))) where 1
+Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on((<in_optimizer>(`test`.`B`.`A`,`test`.`B`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`B`.`A` in <temporAry tABle> on distinct_key where ((`test`.`B`.`A` = `<suBquery2>`.`pk`))))) And (`test`.`A`.`A` = `test`.`t1`.`A`))) where 1
t2 should be wrapped into OJ-nest, so we have "t1 LJ (t2 J t10)"
explAin extended
select * from t1 left join t2 on (t2.A= t1.A And t2.A in (select pk from t10));
id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
-2 DEPENDENT SUBQUERY t10 unique_suBquery PRIMARY PRIMARY 4 func 1 100.00 Using index
+2 SUBQUERY t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on((<in_optimizer>(`test`.`t2`.`A`,<exists>(<primAry_index_lookup>(<cAche>(`test`.`t2`.`A`) in t10 on PRIMARY))) And (`test`.`t2`.`A` = `test`.`t1`.`A`))) where 1
+Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on((<in_optimizer>(`test`.`t2`.`A`,`test`.`t2`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`t2`.`A` in <temporAry tABle> on distinct_key where ((`test`.`t2`.`A` = `<suBquery2>`.`pk`))))) And (`test`.`t2`.`A` = `test`.`t1`.`A`))) where 1
we shouldn't flatten if we're going to get a join of > MAX_TABLES.
explain select * from
t1 s00, t1 s01, t1 s02, t1 s03, t1 s04,t1 s05,t1 s06,t1 s07,t1 s08,t1 s09,
@@ -724,9 +724,10 @@ SELECT int_key FROM ot1
WHERE int_nokey IN (SELECT it2.int_key
FROM it1 LEFT JOIN it2 ON it2.datetime_key);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it1 index NULL int_key 4 NULL 2 Using index; Start temporary
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using join buffer (flat, BNL join)
-1 PRIMARY it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where; End temporary
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 11
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY it1 index NULL int_key 4 NULL 2 Using index
+2 SUBQUERY it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where
DROP TABLE ot1, it1, it2;
# End of BUG#38075
#
@@ -798,9 +799,10 @@ INSERT INTO t2 VALUES (1,'i','iiii','iiii','iiii','iiii','ffff','ffff','ffff','f
EXPLAIN EXTENDED SELECT pk FROM t1 WHERE (a, b) IN (SELECT a, b FROM t2 WHERE pk > 0);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-1 PRIMARY t2 range PRIMARY PRIMARY 4 NULL 2 100.00 Using index condition; Using where; Rowid-ordered scan; FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 13 func,func 1 100.00
+2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 2 100.00 Using index condition; Rowid-ordered scan
Warnings:
-Note 1003 select `test`.`t1`.`pk` AS `pk` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`b` = `test`.`t1`.`b`) and (`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t2`.`pk` > 0))
+Note 1003 select `test`.`t1`.`pk` AS `pk` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`pk` > 0))
SELECT pk FROM t1 WHERE (a, b) IN (SELECT a, b FROM t2 WHERE pk > 0);
pk
2
@@ -966,9 +968,10 @@ FROM t1
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
-1 PRIMARY t1 ref varchar_key varchar_key 3 test.t2.varchar_nokey 2 100.00 Using where; FirstMatch(t2)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
+2 SUBQUERY t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`varchar_key` = `test`.`t2`.`varchar_nokey`) and (`test`.`t1`.`varchar_nokey` = `test`.`t2`.`varchar_nokey`) and ((`test`.`t2`.`varchar_nokey` < 'n') xor `test`.`t1`.`pk`))
+Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key`) and ((`test`.`t1`.`varchar_key` < 'n') xor `test`.`t1`.`pk`))
SELECT varchar_nokey
FROM t2
WHERE ( `varchar_nokey` , `varchar_nokey` ) IN (
@@ -1046,9 +1049,11 @@ WHERE t2.val LIKE 'a%' OR t2.val LIKE 'e%')
AND t1.val IN (SELECT t3.val FROM t3
WHERE t3.val LIKE 'a%' OR t3.val LIKE 'e%');
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Start temporary
-1 PRIMARY t3 ALL NULL NULL NULL NULL 5 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; End temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 14 func 1
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 14 func 1
+3 SUBQUERY t3 ALL NULL NULL NULL NULL 5 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
SELECT *
FROM t1
WHERE t1.val IN (SELECT t2.val FROM t2
@@ -1266,10 +1271,12 @@ explain
select * from t1 A, t1 B
where A.a = B.a and A.a in (select a from t2 C) and B.a in (select a from t2 D);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY A ALL NULL NULL NULL NULL 3 Start temporary
+1 PRIMARY A ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
1 PRIMARY B ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY C ALL NULL NULL NULL NULL 3 Using where
-1 PRIMARY D ALL NULL NULL NULL NULL 3 Using where; End temporary
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY C ALL NULL NULL NULL NULL 3
+3 SUBQUERY D ALL NULL NULL NULL NULL 3
drop table t1, t2;
#
# BUG#784441: Abort on semijoin with a view as the inner table
@@ -1284,7 +1291,7 @@ SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
-2 DEPENDENT SUBQUERY <derived3> system NULL NULL NULL NULL 1
+2 SUBQUERY <derived3> system NULL NULL NULL NULL 1
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1);
a a
@@ -1387,9 +1394,10 @@ insert into t3 values('three'),( 'four');
insert into t3 values('three'),( 'four');
explain select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
-1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; End temporary; Using join buffer (flat, BNL join)
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
b
drop table t1, t2, t3;
@@ -2060,4 +2068,37 @@ a
3
set optimizer_switch= @tmp_otimizer_switch;
drop table t1,t2;
+#
+# Bug #887496: semijoin with IN equality for the second part of an index
+#
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (9), (0), (8), (5);
+CREATE TABLE t2 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t2 VALUES (5,'r'), (5,'z');
+CREATE TABLE t3 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t3 VALUES (5,'r'), (5,'z');
+set @tmp_otimizer_switch= @@optimizer_switch;
+SET SESSION optimizer_switch='semijoin=on,firstmatch=on';
+SET SESSION optimizer_switch='loosescan=off';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 index idx idx 9 NULL 2 Using where; Using index; Start temporary
+1 PRIMARY t3 ref idx idx 4 test.t2.b 1 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+a
+5
+SET SESSION optimizer_switch='loosescan=on';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 index idx idx 9 NULL 2 Using where; Using index; Start temporary
+1 PRIMARY t3 ref idx idx 4 test.t2.b 1 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+a
+5
+set optimizer_switch= @tmp_otimizer_switch;
+DROP TABLE t1,t2,t3;
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/r/subselect_sj2.result b/mysql-test/r/subselect_sj2.result
index b410df3bab9..c95aaab1c13 100644
--- a/mysql-test/r/subselect_sj2.result
+++ b/mysql-test/r/subselect_sj2.result
@@ -46,8 +46,9 @@ a b
19 14
explain select * from t2 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Start temporary
-1 PRIMARY t2 ref b b 5 test.t1.a 2 End temporary
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
+1 PRIMARY t2 ref b b 5 test.t1.a 2
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
select * from t2 where b in (select a from t1);
a b
1 1
@@ -65,8 +66,9 @@ insert into t3 select a,a, a,a,a from t0;
insert into t3 select a,a, a+100,a+100,a+100 from t0;
explain select * from t3 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Start temporary
-1 PRIMARY t3 ref b b 5 test.t1.a 1 End temporary
+1 PRIMARY t3 ALL b NULL NULL NULL 20
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3
select * from t3 where b in (select a from t1);
a b pk1 pk2 pk3
1 1 1 1 1
@@ -90,8 +92,9 @@ A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a
from t0 A, t0 B where B.a <5;
explain select * from t3 where b in (select a from t0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Using where; Start temporary
-1 PRIMARY t3 ref b b 5 test.t0.a 1 End temporary
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10
+1 PRIMARY t3 ref b b 5 test.t0.a 1
+2 SUBQUERY t0 ALL NULL NULL NULL NULL 10 Using where
select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5);
a b pk1 pk2
0 0 0 0
@@ -140,8 +143,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; End temporary; Using join buffer (flat, BNL join)
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
+1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -173,7 +177,8 @@ a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot ALL NULL NULL NULL NULL 22
-1 PRIMARY it ALL NULL NULL NULL NULL 32 Using where; FirstMatch(ot)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY it ALL NULL NULL NULL NULL 32
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
@@ -206,8 +211,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it ALL NULL NULL NULL NULL 22 Start temporary
-1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; End temporary; Using join buffer (flat, BNL join)
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
+1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -239,7 +245,8 @@ a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot ALL NULL NULL NULL NULL 22
-1 PRIMARY it ALL NULL NULL NULL NULL 52 Using where; FirstMatch(ot)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY it ALL NULL NULL NULL NULL 52
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
@@ -279,9 +286,10 @@ from t0 where a in
(select t2.a+t3.a from t1 left join (t2 join t3) on t2.a=t1.a and t3.a=t1.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 10
-1 PRIMARY t1 index a a 5 NULL 10 Using where; Using index
-1 PRIMARY t2 ref a a 5 test.t1.a 1 Using index
-1 PRIMARY t3 ref a a 5 test.t1.a 1 Using index; FirstMatch(t0)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 9 func 1 Using where
+2 SUBQUERY t1 index a a 5 NULL 10 Using where; Using index
+2 SUBQUERY t2 ref a a 5 test.t1.a 1 Using index
+2 SUBQUERY t3 ref a a 5 test.t1.a 1 Using index
drop table t0, t1,t2,t3;
CREATE TABLE t1 (
ID int(11) NOT NULL auto_increment,
@@ -358,7 +366,8 @@ WHERE t1.Code IN (
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 31
-1 PRIMARY t2 ref CountryCode CountryCode 3 test.t1.Code 18 Using where; FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 3 func 1
+2 SUBQUERY t2 ALL CountryCode NULL NULL NULL 545 Using where
SELECT Name FROM t1
WHERE t1.Code IN (
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
@@ -593,7 +602,7 @@ select * from t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t3));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where
-2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY PRIMARY 4 func 1 Using index
+2 SUBQUERY t3 index PRIMARY PRIMARY 4 NULL 10 Using index
drop table t0, t1, t2, t3;
create table t1 (a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -705,8 +714,9 @@ alter table t3 add primary key(id), add key(a);
The following must use loose index scan over t3, key a:
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index a a 5 NULL 1000 Using where; Using index
-1 PRIMARY t3 ref a a 5 test.t2.a 30 Using index; FirstMatch(t2)
+1 PRIMARY t2 index a a 5 NULL 1000 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY t3 index a a 5 NULL 30000 Using index
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
1000
@@ -861,10 +871,11 @@ EXPLAIN
SELECT * FROM t3 LEFT JOIN (v1,t2) ON t3.a = t2.a
WHERE t3.b IN (SELECT b FROM t4);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Start temporary
+1 PRIMARY t3 ALL NULL NULL NULL NULL 1
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 2
-1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; End temporary
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY t4 ALL NULL NULL NULL NULL 2
3 DERIVED t1 ALL NULL NULL NULL NULL 1
SELECT * FROM t3 LEFT JOIN (v1,t2) ON t3.a = t2.a
WHERE t3.b IN (SELECT b FROM t4);
diff --git a/mysql-test/r/subselect_sj2_jcl6.result b/mysql-test/r/subselect_sj2_jcl6.result
index f47fa06996e..48797f5cdd6 100644
--- a/mysql-test/r/subselect_sj2_jcl6.result
+++ b/mysql-test/r/subselect_sj2_jcl6.result
@@ -55,8 +55,9 @@ a b
19 14
explain select * from t2 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Start temporary
-1 PRIMARY t2 ref b b 5 test.t1.a 2 End temporary; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
+1 PRIMARY t2 ref b b 5 test.t1.a 2 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
select * from t2 where b in (select a from t1);
a b
1 1
@@ -74,8 +75,9 @@ insert into t3 select a,a, a,a,a from t0;
insert into t3 select a,a, a+100,a+100,a+100 from t0;
explain select * from t3 where b in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Start temporary
-1 PRIMARY t3 ref b b 5 test.t1.a 1 End temporary; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+1 PRIMARY t3 ALL b NULL NULL NULL 20
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3
select * from t3 where b in (select a from t1);
a b pk1 pk2 pk3
1 1 1 1 1
@@ -99,8 +101,9 @@ A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a, A.a + 10*B.a
from t0 A, t0 B where B.a <5;
explain select * from t3 where b in (select a from t0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Using where; Start temporary
-1 PRIMARY t3 ref b b 5 test.t0.a 1 End temporary; (flat, BKA join); Key-ordered Rowid-ordered scan
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10
+1 PRIMARY t3 ref b b 5 test.t0.a 1 (flat, BKA join); Key-ordered Rowid-ordered scan
+2 SUBQUERY t0 ALL NULL NULL NULL NULL 10 Using where
select * from t3 where b in (select A.a+B.a from t0 A, t0 B where B.a<5);
a b pk1 pk2
0 0 0 0
@@ -149,8 +152,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it ALL NULL NULL NULL NULL 22 Using where; Start temporary
-1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 32 Using where; End temporary; Using join buffer (flat, BNLH join)
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
+1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 32 Using where; Using join buffer (flat, BNLH join)
+2 SUBQUERY it ALL NULL NULL NULL NULL 22 Using where
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -182,7 +186,8 @@ a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot ALL NULL NULL NULL NULL 22
-1 PRIMARY it ALL NULL NULL NULL NULL 32 Using where; FirstMatch(ot); Using join buffer (flat, BNL join)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY it ALL NULL NULL NULL NULL 32
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
@@ -206,8 +211,8 @@ a mid(filler1, 1,10) length(filler1)=length(filler2)
16 filler1234 1
17 filler1234 1
18 filler1234 1
-3 duplicate 1
19 filler1234 1
+3 duplicate 1
19 duplicate 1
insert into t1 select a+20, 'filler123456', 'filler123456' from t0;
insert into t1 select a+20, 'filler123456', 'filler123456' from t0;
@@ -215,8 +220,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it ALL NULL NULL NULL NULL 22 Using where; Start temporary
-1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 52 Using where; End temporary; Using join buffer (flat, BNLH join)
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
+1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 52 Using where; Using join buffer (flat, BNLH join)
+2 SUBQUERY it ALL NULL NULL NULL NULL 22 Using where
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -248,7 +254,8 @@ a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot ALL NULL NULL NULL NULL 22
-1 PRIMARY it ALL NULL NULL NULL NULL 52 Using where; FirstMatch(ot); Using join buffer (flat, BNL join)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY it ALL NULL NULL NULL NULL 52
select
a, mid(filler1, 1,10), length(filler1)=length(filler2)
from t2 ot where a in (select a from t1 it);
@@ -272,8 +279,8 @@ a mid(filler1, 1,10) length(filler1)=length(filler2)
16 filler1234 1
17 filler1234 1
18 filler1234 1
-3 duplicate 1
19 filler1234 1
+3 duplicate 1
19 duplicate 1
drop table t1, t2;
create table t1 (a int, b int, key(a));
@@ -288,9 +295,10 @@ from t0 where a in
(select t2.a+t3.a from t1 left join (t2 join t3) on t2.a=t1.a and t3.a=t1.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t0 ALL NULL NULL NULL NULL 10
-1 PRIMARY t1 index a a 5 NULL 10 Using where; Using index
-1 PRIMARY t2 ref a a 5 test.t1.a 1 Using index
-1 PRIMARY t3 ref a a 5 test.t1.a 1 Using index; FirstMatch(t0)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 9 func 1 Using where
+2 SUBQUERY t1 index a a 5 NULL 10 Using where; Using index
+2 SUBQUERY t2 ref a a 5 test.t1.a 1 Using index
+2 SUBQUERY t3 ref a a 5 test.t1.a 1 Using index
drop table t0, t1,t2,t3;
CREATE TABLE t1 (
ID int(11) NOT NULL auto_increment,
@@ -367,7 +375,8 @@ WHERE t1.Code IN (
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 31
-1 PRIMARY t2 ref CountryCode CountryCode 3 test.t1.Code 18 Using where; FirstMatch(t1); Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 3 func 1
+2 SUBQUERY t2 ALL CountryCode NULL NULL NULL 545 Using where
SELECT Name FROM t1
WHERE t1.Code IN (
SELECT t2.CountryCode FROM t2 WHERE Population > 5000000);
@@ -604,7 +613,7 @@ select * from t1 left join t2 on (t2.a= t1.a and t2.a in (select pk from t3));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY t2 hash_ALL NULL #hash#$hj 5 test.t1.a 3 Using where; Using join buffer (flat, BNLH join)
-2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY PRIMARY 4 func 1 Using index
+2 SUBQUERY t3 index PRIMARY PRIMARY 4 NULL 10 Using index
drop table t0, t1, t2, t3;
create table t1 (a int);
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
@@ -716,8 +725,9 @@ alter table t3 add primary key(id), add key(a);
The following must use loose index scan over t3, key a:
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index a a 5 NULL 1000 Using where; Using index
-1 PRIMARY t3 ref a a 5 test.t2.a 30 Using index; FirstMatch(t2)
+1 PRIMARY t2 index a a 5 NULL 1000 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY t3 index a a 5 NULL 30000 Using index
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
1000
@@ -872,10 +882,11 @@ EXPLAIN
SELECT * FROM t3 LEFT JOIN (v1,t2) ON t3.a = t2.a
WHERE t3.b IN (SELECT b FROM t4);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Using where; Start temporary
+1 PRIMARY t3 ALL NULL NULL NULL NULL 1
1 PRIMARY t2 hash_ALL NULL #hash#$hj 5 test.t3.a 1 Using where; Using join buffer (flat, BNLH join)
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 2 Using join buffer (incremental, BNL join)
-1 PRIMARY t4 hash_ALL NULL #hash#$hj 5 test.t3.b 2 Using where; End temporary; Using join buffer (incremental, BNLH join)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY t4 ALL NULL NULL NULL NULL 2
3 DERIVED t1 ALL NULL NULL NULL NULL 1
SELECT * FROM t3 LEFT JOIN (v1,t2) ON t3.a = t2.a
WHERE t3.b IN (SELECT b FROM t4);
diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result
index a07f43dd288..1b7fccf924c 100644
--- a/mysql-test/r/subselect_sj2_mat.result
+++ b/mysql-test/r/subselect_sj2_mat.result
@@ -890,4 +890,4 @@ set optimizer_switch=@subselect_sj2_tmp;
set optimizer_switch=default;
select @@optimizer_switch like '%materialization=on%';
@@optimizer_switch like '%materialization=on%'
-0
+1
diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result
index 17ed56092c3..b697939d4bc 100644
--- a/mysql-test/r/subselect_sj_jcl6.result
+++ b/mysql-test/r/subselect_sj_jcl6.result
@@ -90,18 +90,18 @@ id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY A ALL NULL NULL NULL NULL 3 100.00 Using where; Using join Buffer (flAt, BNL join)
1 PRIMARY B ALL NULL NULL NULL NULL 3 100.00 Using where; Using join Buffer (incrementAl, BNL join)
-2 DEPENDENT SUBQUERY t10 unique_suBquery PRIMARY PRIMARY 4 func 1 100.00 Using index
+2 SUBQUERY t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on((<in_optimizer>(`test`.`B`.`A`,<exists>(<primAry_index_lookup>(<cAche>(`test`.`B`.`A`) in t10 on PRIMARY))) And (`test`.`A`.`A` = `test`.`t1`.`A`))) where 1
+Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`A`.`A` AS `A`,`test`.`A`.`B` AS `B`,`test`.`B`.`A` AS `A`,`test`.`B`.`B` AS `B` from `test`.`t1` left join (`test`.`t2` `A` join `test`.`t2` `B`) on((<in_optimizer>(`test`.`B`.`A`,`test`.`B`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`B`.`A` in <temporAry tABle> on distinct_key where ((`test`.`B`.`A` = `<suBquery2>`.`pk`))))) And (`test`.`A`.`A` = `test`.`t1`.`A`))) where 1
t2 should be wrapped into OJ-nest, so we have "t1 LJ (t2 J t10)"
explAin extended
select * from t1 left join t2 on (t2.A= t1.A And t2.A in (select pk from t10));
id select_type tABle type possiBle_keys key key_len ref rows filtered ExtrA
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join Buffer (flAt, BNL join)
-2 DEPENDENT SUBQUERY t10 unique_suBquery PRIMARY PRIMARY 4 func 1 100.00 Using index
+2 SUBQUERY t10 index PRIMARY PRIMARY 4 NULL 10 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on((<in_optimizer>(`test`.`t2`.`A`,<exists>(<primAry_index_lookup>(<cAche>(`test`.`t2`.`A`) in t10 on PRIMARY))) And (`test`.`t2`.`A` = `test`.`t1`.`A`))) where 1
+Note 1003 select `test`.`t1`.`A` AS `A`,`test`.`t1`.`B` AS `B`,`test`.`t2`.`A` AS `A`,`test`.`t2`.`B` AS `B` from `test`.`t1` left join `test`.`t2` on((<in_optimizer>(`test`.`t2`.`A`,`test`.`t2`.`A` in ( <mAteriAlize> (select `test`.`t10`.`pk` from `test`.`t10` ), <primAry_index_lookup>(`test`.`t2`.`A` in <temporAry tABle> on distinct_key where ((`test`.`t2`.`A` = `<suBquery2>`.`pk`))))) And (`test`.`t2`.`A` = `test`.`t1`.`A`))) where 1
we shouldn't flatten if we're going to get a join of > MAX_TABLES.
explain select * from
t1 s00, t1 s01, t1 s02, t1 s03, t1 s04,t1 s05,t1 s06,t1 s07,t1 s08,t1 s09,
@@ -735,9 +735,10 @@ SELECT int_key FROM ot1
WHERE int_nokey IN (SELECT it2.int_key
FROM it1 LEFT JOIN it2 ON it2.datetime_key);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY it1 index NULL int_key 4 NULL 2 Using index; Start temporary
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using join buffer (flat, BNL join)
-1 PRIMARY it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where; End temporary; Using join buffer (incremental, BNL join)
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 11
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY it1 index NULL int_key 4 NULL 2 Using index
+2 SUBQUERY it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
DROP TABLE ot1, it1, it2;
# End of BUG#38075
#
@@ -809,9 +810,10 @@ INSERT INTO t2 VALUES (1,'i','iiii','iiii','iiii','iiii','ffff','ffff','ffff','f
EXPLAIN EXTENDED SELECT pk FROM t1 WHERE (a, b) IN (SELECT a, b FROM t2 WHERE pk > 0);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
-1 PRIMARY t2 range PRIMARY PRIMARY 4 NULL 2 100.00 Using index condition; Using where; Rowid-ordered scan; FirstMatch(t1); Using join buffer (flat, BNL join)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 13 func,func 1 100.00
+2 SUBQUERY t2 range PRIMARY PRIMARY 4 NULL 2 100.00 Using index condition; Rowid-ordered scan
Warnings:
-Note 1003 select `test`.`t1`.`pk` AS `pk` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`b` = `test`.`t1`.`b`) and (`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t2`.`pk` > 0))
+Note 1003 select `test`.`t1`.`pk` AS `pk` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`pk` > 0))
SELECT pk FROM t1 WHERE (a, b) IN (SELECT a, b FROM t2 WHERE pk > 0);
pk
2
@@ -977,9 +979,10 @@ FROM t1
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
-1 PRIMARY t1 ref varchar_key varchar_key 3 test.t2.varchar_nokey 2 100.00 Using where; FirstMatch(t2); Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
+2 SUBQUERY t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`varchar_key` = `test`.`t2`.`varchar_nokey`) and (`test`.`t1`.`varchar_nokey` = `test`.`t2`.`varchar_nokey`) and ((`test`.`t2`.`varchar_nokey` < 'n') xor `test`.`t1`.`pk`))
+Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key`) and ((`test`.`t1`.`varchar_key` < 'n') xor `test`.`t1`.`pk`))
SELECT varchar_nokey
FROM t2
WHERE ( `varchar_nokey` , `varchar_nokey` ) IN (
@@ -1057,9 +1060,11 @@ WHERE t2.val LIKE 'a%' OR t2.val LIKE 'e%')
AND t1.val IN (SELECT t3.val FROM t3
WHERE t3.val LIKE 'a%' OR t3.val LIKE 'e%');
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Start temporary
-1 PRIMARY t3 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (incremental, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 14 func 1
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 14 func 1
+3 SUBQUERY t3 ALL NULL NULL NULL NULL 5 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 6 Using where
SELECT *
FROM t1
WHERE t1.val IN (SELECT t2.val FROM t2
@@ -1277,10 +1282,12 @@ explain
select * from t1 A, t1 B
where A.a = B.a and A.a in (select a from t2 C) and B.a in (select a from t2 D);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY A ALL NULL NULL NULL NULL 3 Start temporary
+1 PRIMARY A ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 5 func 1
1 PRIMARY B ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY C ALL NULL NULL NULL NULL 3 Using where; Using join buffer (incremental, BNL join)
-1 PRIMARY D ALL NULL NULL NULL NULL 3 Using where; End temporary; Using join buffer (incremental, BNL join)
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 5 func 1
+2 SUBQUERY C ALL NULL NULL NULL NULL 3
+3 SUBQUERY D ALL NULL NULL NULL NULL 3
drop table t1, t2;
#
# BUG#784441: Abort on semijoin with a view as the inner table
@@ -1295,7 +1302,7 @@ SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
-2 DEPENDENT SUBQUERY <derived3> system NULL NULL NULL NULL 1
+2 SUBQUERY <derived3> system NULL NULL NULL NULL 1
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT * FROM t1 INNER JOIN t2 ON t2.a != 0 AND t2.a IN (SELECT * FROM v1);
a a
@@ -1398,9 +1405,10 @@ insert into t3 values('three'),( 'four');
insert into t3 values('three'),( 'four');
explain select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; End temporary; Using join buffer (incremental, BNL join)
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 2
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
b
drop table t1, t2, t3;
@@ -2071,6 +2079,39 @@ a
3
set optimizer_switch= @tmp_otimizer_switch;
drop table t1,t2;
+#
+# Bug #887496: semijoin with IN equality for the second part of an index
+#
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (9), (0), (8), (5);
+CREATE TABLE t2 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t2 VALUES (5,'r'), (5,'z');
+CREATE TABLE t3 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t3 VALUES (5,'r'), (5,'z');
+set @tmp_otimizer_switch= @@optimizer_switch;
+SET SESSION optimizer_switch='semijoin=on,firstmatch=on';
+SET SESSION optimizer_switch='loosescan=off';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 index idx idx 9 NULL 2 Using where; Using index; Start temporary
+1 PRIMARY t3 ref idx idx 4 test.t2.b 1 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+a
+5
+SET SESSION optimizer_switch='loosescan=on';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 index idx idx 9 NULL 2 Using where; Using index; Start temporary
+1 PRIMARY t3 ref idx idx 4 test.t2.b 1 Using index
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; End temporary; Using join buffer (flat, BNL join)
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+a
+5
+set optimizer_switch= @tmp_otimizer_switch;
+DROP TABLE t1,t2,t3;
set optimizer_switch=@subselect_sj_tmp;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
@@ -2104,6 +2145,54 @@ a
3
set optimizer_switch=@save_optimizer_switch;
drop table t0, t1, t2;
+#
+# Bug #891995: IN subquery with join_cache_level >= 3
+#
+CREATE TABLE t1 (a varchar(1));
+INSERT INTO t1 VALUES ('w'),('q');
+CREATE TABLE t2 (a int NOT NULL, b time, PRIMARY KEY (a));
+INSERT INTO t2 VALUES
+(2,'18:56:33'), (5,'19:11:10'), (3,'18:56:33'), (7,'19:11:10');
+CREATE TABLE t3 (
+a int NOT NULL, b int, c int, d varchar(1), PRIMARY KEY (a), KEY (d,c)
+);
+INSERT INTO t3 VALUES
+(25,158,10,'f'), (26,5,2,'v'), (27,163,103,'f'), (28,2,3,'q'), (29,8,6,'y');
+set @save_optimizer_switch=@@optimizer_switch;
+SET SESSION optimizer_switch='semijoin=on';
+SET SESSION optimizer_switch='join_cache_hashed=on';
+SET SESSION join_cache_level=3;
+EXPLAIN
+SELECT * FROM t1, t2
+WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t3 ALL d NULL NULL NULL 5 Range checked for each record (index map: 0x2)
+1 PRIMARY t2 hash_ALL PRIMARY #hash#PRIMARY 4 test.t3.b 4 End temporary; Using join buffer (flat, BNLH join)
+SELECT * FROM t1, t2
+WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
+a a b
+w 2 18:56:33
+q 2 18:56:33
+w 5 19:11:10
+SET SESSION optimizer_switch='mrr=on';
+SET SESSION join_cache_level=6;
+EXPLAIN
+SELECT * FROM t1, t2
+WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Start temporary
+1 PRIMARY t3 ALL d NULL NULL NULL 5 Range checked for each record (index map: 0x2)
+1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t3.b 1 End temporary; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
+SELECT * FROM t1, t2
+WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
+a a b
+w 2 18:56:33
+q 2 18:56:33
+w 5 19:11:10
+set optimizer_switch=@save_optimizer_switch;
+set join_cache_level=default;
+DROP TABLE t1,t2,t3;
# End
set join_cache_level=default;
show variables like 'join_cache_level';
diff --git a/mysql-test/r/table_elim.result b/mysql-test/r/table_elim.result
index 892ac29d6d5..4b4ea83fcce 100644
--- a/mysql-test/r/table_elim.result
+++ b/mysql-test/r/table_elim.result
@@ -128,7 +128,7 @@ Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` where (`f`.`id` in (1,2,3
This should use facts and a1 tables:
explain extended select id from v1 where attr1 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE a1 range PRIMARY,attr1 attr1 5 NULL 2 100.00 Using where
+1 SIMPLE a1 range PRIMARY,attr1 attr1 5 NULL 2 100.00 Using index condition
1 SIMPLE f eq_ref PRIMARY PRIMARY 4 test.a1.id 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #2
@@ -136,7 +136,7 @@ Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t1` `a1` whe
This should use facts, a2 and its subquery:
explain extended select id from v1 where attr2 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE a2 range PRIMARY,attr2 attr2 5 NULL 5 100.00 Using where
+1 SIMPLE a2 range PRIMARY,attr2 attr2 5 NULL 5 100.00 Using index condition; Using where
1 SIMPLE f eq_ref PRIMARY PRIMARY 4 test.a2.id 1 100.00 Using index
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.a2.id 2 100.00 Using index
Warnings:
@@ -156,7 +156,7 @@ Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` where (`f`.`id` in (1,2,3
This should use facts and a1 tables:
explain extended select id from v2 where attr1 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE a1 range PRIMARY,attr1 attr1 5 NULL 2 100.00 Using where
+1 SIMPLE a1 range PRIMARY,attr1 attr1 5 NULL 2 100.00 Using index condition
1 SIMPLE f eq_ref PRIMARY PRIMARY 4 test.a1.id 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
@@ -164,7 +164,7 @@ Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t1` `a1` whe
This should use facts, a2 and its subquery:
explain extended select id from v2 where attr2 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE a2 range PRIMARY,attr2 attr2 5 NULL 5 100.00 Using where
+1 SIMPLE a2 range PRIMARY,attr2 attr2 5 NULL 5 100.00 Using index condition
1 SIMPLE f eq_ref PRIMARY PRIMARY 4 test.a2.id 1 100.00 Using where; Using index
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.f.id 2 100.00 Using index
Warnings:
diff --git a/mysql-test/suite/innodb/r/innodb_gis.result b/mysql-test/suite/innodb/r/innodb_gis.result
index 566b950d430..d401093cabc 100644
--- a/mysql-test/suite/innodb/r/innodb_gis.result
+++ b/mysql-test/suite/innodb/r/innodb_gis.result
@@ -236,7 +236,7 @@ explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelo
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 100.00
Warnings:
-Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry`
+Note 1003 select st_dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,st_geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,st_isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,st_astext(st_envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry`
SELECT fid, X(g) FROM gis_point ORDER by fid;
fid X(g)
101 10
@@ -253,7 +253,7 @@ explain extended select X(g),Y(g) FROM gis_point;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 100.00
Warnings:
-Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point`
+Note 1003 select st_x(`test`.`gis_point`.`g`) AS `X(g)`,st_y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point`
SELECT fid, AsText(StartPoint(g)) FROM gis_line ORDER by fid;
fid AsText(StartPoint(g))
105 POINT(0 0)
@@ -288,7 +288,7 @@ explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),Num
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line`
+Note 1003 select st_astext(st_startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,st_astext(st_endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,st_length(`test`.`gis_line`.`g`) AS `GLength(g)`,st_numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,st_astext(st_pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,st_isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line`
SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid;
fid AsText(Centroid(g))
108 POINT(15 15)
@@ -318,7 +318,7 @@ explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumI
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon`
+Note 1003 select st_astext(st_centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,st_area(`test`.`gis_polygon`.`g`) AS `Area(g)`,st_astext(st_exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,st_numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,st_astext(st_interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon`
SELECT fid, IsClosed(g) FROM gis_multi_line ORDER by fid;
fid IsClosed(g)
114 0
@@ -357,7 +357,7 @@ explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point`
+Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,st_numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point`
SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point ORDER by fid;
fid AsText(GeometryN(g, 2))
111 POINT(10 10)
@@ -385,17 +385,17 @@ explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point`
+Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,st_astext(st_geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point`
SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
first second w c o e d t i r
-120 120 1 1 0 1 0 0 1 0
+120 120 1 1 0 1 0 1 1 0
120 121 0 0 1 0 0 0 1 0
121 120 0 0 1 0 0 0 1 0
-121 121 1 1 0 1 0 0 1 0
+121 121 1 1 0 1 0 1 1 0
explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
@@ -405,7 +405,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE g1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
1 SIMPLE g2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
-Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid`
+Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,st_within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,st_contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,mbroverlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,st_equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,mbrdisjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,st_touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,mbrintersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,st_crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid`
DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
CREATE TABLE t1 (
a INTEGER PRIMARY KEY AUTO_INCREMENT,
@@ -494,7 +494,7 @@ mbroverlaps
down,left,right,up
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrtouches FROM t1 a1 JOIN t1 a2 ON MBRTouches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
mbrtouches
-down2,left2,right2,up2
+big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1 a2 ON MBRWithin( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
mbrwithin
big,center
@@ -515,7 +515,7 @@ overlaps
down,left,right,up
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS touches FROM t1 a1 JOIN t1 a2 ON Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
touches
-down2,left2,right2,up2
+big,center,down,down2,left,left2,right,right2,small,up,up2
SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS within FROM t1 a1 JOIN t1 a2 ON Within( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name;
within
big,center
diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result
index 8e41a951ab8..813288fe601 100644
--- a/mysql-test/suite/innodb/r/innodb_mysql.result
+++ b/mysql-test/suite/innodb/r/innodb_mysql.result
@@ -2880,7 +2880,7 @@ SELECT t1.a FROM t1 LEFT JOIN t2 ON t1.pk = t2.a
WHERE t1.pk >= 6 HAVING t1.a<> 0 AND t1.a <> 11
ORDER BY t1.a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using filesort
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using index condition; Using filesort
1 SIMPLE t2 ref a a 5 test.t1.pk 1 Using index
SELECT t1.a FROM t1 LEFT JOIN t2 ON t1.pk = t2.a
WHERE t1.pk >= 6 HAVING t1.a<> 0 AND t1.a <> 11
diff --git a/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test
index f861d8de445..5a0aaa86d4c 100644
--- a/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test
+++ b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test
@@ -139,6 +139,7 @@ insert into t1 values (1,1), (2,null), (3,1), (4,1),
--echo # used later in the test JT_EQ_REF access method is used.
--echo #
--vertical_results
+--replace_result "Using index condition; Using where" "Using where"
explain
select 1 from t1 natural join (select 2 as a, 1 as b union all
select 2 as a, 2 as b) as t2 for update;
@@ -235,6 +236,7 @@ begin;
--echo #
--echo # Verify that JT_EQ_REF is used.
--vertical_results
+--replace_result "Using index condition; Using where" "Using where"
explain
select 1 from t1 natural join (select 3 as a, 2 as b union all
select 3 as a, 1 as b) as t2 for update;
diff --git a/mysql-test/suite/innodb/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test
index d379e63f505..4cdcf2ce5cd 100644
--- a/mysql-test/suite/innodb/t/innodb_mysql.test
+++ b/mysql-test/suite/innodb/t/innodb_mysql.test
@@ -1041,6 +1041,8 @@ INSERT INTO t1 VALUES
SET SESSION join_cache_level = 0;
+# vanilla InnoDB doesn't do ICP
+--replace_result "Using where" "Using index condition"
EXPLAIN
SELECT t1.a FROM t1 LEFT JOIN t2 ON t1.pk = t2.a
WHERE t1.pk >= 6 HAVING t1.a<> 0 AND t1.a <> 11
diff --git a/mysql-test/suite/maria/r/maria-gis-rtree-dynamic.result b/mysql-test/suite/maria/r/maria-gis-rtree-dynamic.result
index 743f1785f5c..843e5ae3d37 100644
--- a/mysql-test/suite/maria/r/maria-gis-rtree-dynamic.result
+++ b/mysql-test/suite/maria/r/maria-gis-rtree-dynamic.result
@@ -168,7 +168,7 @@ count(*)
150
EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range g g 34 NULL 11 Using where
+1 SIMPLE t1 ALL g NULL NULL NULL 150 Using where
SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
fid AsText(g)
1 LINESTRING(150 150,150 150)
@@ -302,14 +302,10 @@ count(*)
EXPLAIN SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range g g 34 NULL 4 Using where
+1 SIMPLE t2 range g g 34 NULL 1 Using where
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
fid AsText(g)
-45 LINESTRING(51 51,60 60)
-46 LINESTRING(51 41,60 50)
-55 LINESTRING(41 51,50 60)
-56 LINESTRING(41 41,50 50)
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(LineString(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10)))));
SELECT count(*) FROM t2;
count(*)
diff --git a/mysql-test/suite/maria/r/maria-gis-rtree-trans.result b/mysql-test/suite/maria/r/maria-gis-rtree-trans.result
index ae37b9d454d..8ccc1f5bfdf 100644
--- a/mysql-test/suite/maria/r/maria-gis-rtree-trans.result
+++ b/mysql-test/suite/maria/r/maria-gis-rtree-trans.result
@@ -168,7 +168,7 @@ count(*)
150
EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range g g 34 NULL 11 Using where
+1 SIMPLE t1 ALL g NULL NULL NULL 150 Using where
SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
fid AsText(g)
1 LINESTRING(150 150,150 150)
@@ -302,14 +302,10 @@ count(*)
EXPLAIN SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range g g 34 NULL 4 Using where
+1 SIMPLE t2 range g g 34 NULL 1 Using where
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
fid AsText(g)
-45 LINESTRING(51 51,60 60)
-46 LINESTRING(51 41,60 50)
-55 LINESTRING(41 51,50 60)
-56 LINESTRING(41 41,50 50)
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(LineString(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10)))));
SELECT count(*) FROM t2;
count(*)
diff --git a/mysql-test/suite/maria/r/maria-gis-rtree.result b/mysql-test/suite/maria/r/maria-gis-rtree.result
index a61e93d2a3a..9945daae75e 100644
--- a/mysql-test/suite/maria/r/maria-gis-rtree.result
+++ b/mysql-test/suite/maria/r/maria-gis-rtree.result
@@ -168,7 +168,7 @@ count(*)
150
EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range g g 34 NULL 11 Using where
+1 SIMPLE t1 ALL g NULL NULL NULL 150 Using where
SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
fid AsText(g)
1 LINESTRING(150 150,150 150)
@@ -302,14 +302,10 @@ count(*)
EXPLAIN SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range g g 34 NULL 4 Using where
+1 SIMPLE t2 range g g 34 NULL 1 Using where
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
fid AsText(g)
-45 LINESTRING(51 51,60 60)
-46 LINESTRING(51 41,60 50)
-55 LINESTRING(41 51,50 60)
-56 LINESTRING(41 41,50 50)
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(LineString(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10)))));
SELECT count(*) FROM t2;
count(*)
diff --git a/mysql-test/suite/maria/r/maria.result b/mysql-test/suite/maria/r/maria.result
index 320c081382f..36f7301ca0b 100644
--- a/mysql-test/suite/maria/r/maria.result
+++ b/mysql-test/suite/maria/r/maria.result
@@ -401,10 +401,10 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a a 4 test.t2.a 1
explain select * from t1 where a=0 or a=2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 4 NULL 5 Using where
+1 SIMPLE t1 range a a 4 NULL 5 Using index condition; Using where
explain select * from t1 force index (a) where a=0 or a=2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 4 NULL 5 Using where
+1 SIMPLE t1 range a a 4 NULL 5 Using index condition; Using where
explain select * from t1 where c=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref c,c_2 c 5 const 2
diff --git a/mysql-test/suite/pbxt/r/group_by.result b/mysql-test/suite/pbxt/r/group_by.result
index b33c9ac87c2..d20df632ab1 100644
--- a/mysql-test/suite/pbxt/r/group_by.result
+++ b/mysql-test/suite/pbxt/r/group_by.result
@@ -1172,7 +1172,8 @@ EXPLAIN SELECT 1 FROM t1 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index PRIMARY,i2 PRIMARY 4 NULL 144 Using index
-1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Using where; FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 144
CREATE TABLE t2 (a INT, b INT, KEY(a));
INSERT INTO t2 VALUES (1, 1), (2, 2), (3,3), (4,4);
EXPLAIN SELECT a, SUM(b) FROM t2 GROUP BY a LIMIT 2;
@@ -1185,5 +1186,6 @@ EXPLAIN SELECT 1 FROM t2 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index a a 5 NULL 4 Using index
-1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Using where; FirstMatch(t2)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 144
DROP TABLE t1, t2;
diff --git a/mysql-test/suite/pbxt/r/group_min_max.result b/mysql-test/suite/pbxt/r/group_min_max.result
index 2f7a028c862..6985abeeb43 100644
--- a/mysql-test/suite/pbxt/r/group_min_max.result
+++ b/mysql-test/suite/pbxt/r/group_min_max.result
@@ -2256,8 +2256,9 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index NULL a 10 NULL 15 Using where; Using index
-2 DEPENDENT SUBQUERY t1 index NULL a 10 NULL 1 Using index
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 15 Using where
+1 PRIMARY t1_outer ref a a 5 <subquery2>.max(b) 1 Using index
+2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/mysql-test/suite/pbxt/r/null_key.result b/mysql-test/suite/pbxt/r/null_key.result
index cb13822a72f..7ef554af946 100644
--- a/mysql-test/suite/pbxt/r/null_key.result
+++ b/mysql-test/suite/pbxt/r/null_key.result
@@ -76,13 +76,13 @@ insert into t2 select * from t1;
alter table t1 modify b blob not null, add c int not null, drop key a, add unique key (a,b(20),c), drop key b, add key (b(10));
explain select * from t1 where a is null and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a is null and b = 2 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a is null and b = 7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a=2 and b = 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 1 Using where
@@ -91,25 +91,25 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 12 Using where
explain select * from t1 where (a is null or a > 0 and a < 3) and b < 5 and c=0 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 5 NULL 5 Using where
+1 SIMPLE t1 range a,b a 5 NULL 5 Using index condition; Using where
explain select * from t1 where (a is null or a = 7) and b=7 and c=0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref_or_null a,b a 5 const 4 Using where
+1 SIMPLE t1 ref_or_null a,b a 5 const 4 Using index condition; Using where
explain select * from t1 where (a is null and b>a) or a is null and b=7 limit 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a is null and b=9 or a is null and b=7 limit 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a,b a 5 const 3 Using where
+1 SIMPLE t1 ref a,b a 5 const 3 Using index condition; Using where
explain select * from t1 where a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 1 Using where
+1 SIMPLE t1 range a a 5 NULL 1 Using index condition
explain select * from t1 where a is null and b=7 or a > 1 and a < 3 limit 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 5 NULL 4 Using where
+1 SIMPLE t1 range a,b a 5 NULL 4 Using index condition; Using where
explain select * from t1 where a > 8 and a < 9;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 1 Using where
+1 SIMPLE t1 range a a 5 NULL 1 Using index condition
explain select * from t1 where b like "6%";
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 12 NULL 1 Using where
@@ -258,7 +258,7 @@ INSERT INTO t1 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4
INSERT INTO t2 VALUES (1,NULL),(2,NULL),(3,1),(4,2),(5,NULL),(6,NULL),(7,3),(8,4),(9,NULL),(10,NULL);
explain select id from t1 where uniq_id is null;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref idx1 idx1 5 const 5 Using where
+1 SIMPLE t1 ref idx1 idx1 5 const 5 Using index condition
explain select id from t1 where uniq_id =1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const idx1 idx1 5 const 1
diff --git a/mysql-test/suite/pbxt/r/order_by.result b/mysql-test/suite/pbxt/r/order_by.result
index 4fc7abec96c..4f56f433169 100644
--- a/mysql-test/suite/pbxt/r/order_by.result
+++ b/mysql-test/suite/pbxt/r/order_by.result
@@ -514,7 +514,7 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT t1.gid, t3.uid from t1, t3 where t1.skr = t3.uid order by t1.gid,t3.skr;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using temporary; Using filesort
-1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.skr 1 Using where
+1 SIMPLE t3 eq_ref PRIMARY PRIMARY 2 test.t1.skr 1 Using index condition
drop table t1,t2,t3;
CREATE TABLE t1 (
`titre` char(80) NOT NULL default '',
diff --git a/mysql-test/suite/pbxt/r/ps_1general.result b/mysql-test/suite/pbxt/r/ps_1general.result
index 4fe13c4bc50..52eb7529a1b 100644
--- a/mysql-test/suite/pbxt/r/ps_1general.result
+++ b/mysql-test/suite/pbxt/r/ps_1general.result
@@ -468,9 +468,9 @@ def key 253 64 7 Y 0 31 8
def key_len 253 4096 1 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
-def Extra 253 255 27 N 1 31 8
+def Extra 253 255 37 N 1 31 8
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using where; Using filesort
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 3 Using index condition; Using filesort
drop table if exists t2;
create table t2 (id smallint, name varchar(20)) ;
prepare stmt1 from ' insert into t2 values(?, ?) ' ;
diff --git a/mysql-test/suite/pbxt/r/range.result b/mysql-test/suite/pbxt/r/range.result
index 2cef8d8efa4..6ce175e2271 100644
--- a/mysql-test/suite/pbxt/r/range.result
+++ b/mysql-test/suite/pbxt/r/range.result
@@ -277,7 +277,7 @@ INSERT INTO t1 VALUES
(33,5),(33,5),(33,5),(33,5),(34,5),(35,5);
EXPLAIN SELECT * FROM t1 WHERE a IN(1,2) AND b=5;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a,b a 5 NULL 2 Using where
+1 SIMPLE t1 range a,b a 5 NULL 2 Using index condition; Using where
SELECT * FROM t1 WHERE a IN(1,2) AND b=5;
a b
DROP TABLE t1;
@@ -902,7 +902,7 @@ INSERT INTO t1 VALUES
('A2','2005-12-01 08:00:00',1000);
EXPLAIN SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref PRIMARY PRIMARY 20 const 2 Using where
+1 SIMPLE t1 ref PRIMARY PRIMARY 20 const 2 Using index condition
SELECT * FROM t1 WHERE item='A1' AND started<='2005-12-01 24:00:00';
item started price
Warnings:
diff --git a/mysql-test/suite/pbxt/r/subselect.result b/mysql-test/suite/pbxt/r/subselect.result
index c012c2d1c29..46a974b5168 100644
--- a/mysql-test/suite/pbxt/r/subselect.result
+++ b/mysql-test/suite/pbxt/r/subselect.result
@@ -2835,9 +2835,10 @@ Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,<expr_cac
explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 9 100.00 Using where; FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 10 func,func 1 100.00
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 9 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`two` = `test`.`t1`.`two`) and (`test`.`t2`.`one` = `test`.`t1`.`one`) and (`test`.`t2`.`flag` = 'N'))
+Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`flag` = 'N'))
explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 100.00
@@ -3427,7 +3428,8 @@ EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
ALTER TABLE t1 ADD INDEX(a);
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
a b
@@ -3437,8 +3439,9 @@ AAA 8
EXPLAIN
SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 9 Using where
-2 DEPENDENT SUBQUERY t1 index NULL a 8 NULL 1
+1 PRIMARY t1 ALL a NULL NULL NULL 9 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 23 test.t1.a,test.t1.b 1
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 9 Using temporary
DROP TABLE t1;
create table t1( f1 int,f2 int);
insert into t1 values (1,1),(2,2);
diff --git a/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result b/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result
index 0922113f8b6..b09fac99711 100644
--- a/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result
+++ b/mysql-test/suite/sys_vars/r/engine_condition_pushdown_basic.result
@@ -9,7 +9,7 @@ SELECT @global_start_value;
select @old_session_opt_switch:=@@session.optimizer_switch,
@old_global_opt_switch:=@@global.optimizer_switch;
@old_session_opt_switch:=@@session.optimizer_switch @old_global_opt_switch:=@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
'#--------------------FN_DYNVARS_028_01------------------------#'
SET @@session.engine_condition_pushdown = 0;
Warnings:
@@ -212,7 +212,7 @@ select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
set @@session.engine_condition_pushdown = TRUE;
Warnings:
Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead
@@ -220,7 +220,7 @@ select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-1 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+1 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
set @@session.engine_condition_pushdown = FALSE;
Warnings:
Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead
@@ -228,7 +228,7 @@ select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
set @@global.engine_condition_pushdown = TRUE;
Warnings:
Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead
@@ -236,7 +236,7 @@ select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-0 1 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+0 1 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
set @@global.engine_condition_pushdown = FALSE;
Warnings:
Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead
@@ -244,31 +244,31 @@ select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
set @@session.optimizer_switch = "engine_condition_pushdown=on";
select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-1 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+1 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
set @@session.optimizer_switch = "engine_condition_pushdown=off";
select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
set @@global.optimizer_switch = "engine_condition_pushdown=on";
select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-0 1 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+0 1 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
set @@global.optimizer_switch = "engine_condition_pushdown=off";
select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
SET @@session.engine_condition_pushdown = @session_start_value;
Warnings:
Warning 1287 The syntax '@@engine_condition_pushdown' is deprecated and will be removed in MySQL 7.0. Please use '@@optimizer_switch' instead
@@ -287,4 +287,4 @@ select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
index 1fa39374f9c..db768c4a25f 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
@@ -1,25 +1,25 @@
SET @start_global_value = @@global.optimizer_switch;
SELECT @start_global_value;
@start_global_value
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
set global optimizer_switch=10;
set session optimizer_switch=5;
select @@global.optimizer_switch;
@@ -63,4 +63,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
SET @@global.optimizer_switch = @start_global_value;
SELECT @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown1.result b/mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown1.result
index ad618c1727f..5e3af75378f 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown1.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown1.result
@@ -2,4 +2,4 @@ select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-1 1 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+1 1 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown2.result b/mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown2.result
index daed5b2919c..5adcf99675d 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown2.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_eng_cond_pushdown2.result
@@ -2,4 +2,4 @@ select @@session.engine_condition_pushdown,
@@global.engine_condition_pushdown,
@@session.optimizer_switch, @@global.optimizer_switch;
@@session.engine_condition_pushdown @@global.engine_condition_pushdown @@session.optimizer_switch @@global.optimizer_switch
-0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=off,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
+0 0 index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=off,derived_with_keys=off,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on
diff --git a/mysql-test/suite/vcol/r/vcol_select_innodb.result b/mysql-test/suite/vcol/r/vcol_select_innodb.result
index 6dafda87647..0d8f1f03db3 100644
--- a/mysql-test/suite/vcol/r/vcol_select_innodb.result
+++ b/mysql-test/suite/vcol/r/vcol_select_innodb.result
@@ -22,7 +22,7 @@ a b c
1 -1 -1
explain select * from t2 where c=-1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref c c 5 const 1 Using where
+1 SIMPLE t2 ref c c 5 const 1 Using index condition
# select_type=SIMPLE, type=ALL
select * from t1 where b=-1;
a b c
@@ -44,7 +44,7 @@ a b c
1 -1 -1
explain select * from t3 where c>=-1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 1 Using where
+1 SIMPLE t3 range c c 5 NULL 1 Using index condition
# select_type=SIMPLE, type=ref
select * from t1,t3 where t1.c=t3.c and t3.c=-1;
a b c a b c
@@ -53,7 +53,7 @@ a b c a b c
explain select * from t1,t3 where t1.c=t3.c and t3.c=-1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 const c c 5 const 1
-1 SIMPLE t1 ref c c 5 const 2 Using where
+1 SIMPLE t1 ref c c 5 const 2 Using index condition
# select_type=PRIMARY, type=index,ALL
select * from t1 where b in (select c from t3);
a b c
@@ -141,7 +141,7 @@ a b c
1 -1 -1
explain select * from t3 where c >= -2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 2 Using where
+1 SIMPLE t3 range c c 5 NULL 2 Using index condition
# SELECT * FROM tbl_name WHERE <non-vcol expr>
select * from t3 where a between 1 and 2;
a b c
@@ -149,7 +149,7 @@ a b c
2 -2 -2
explain select * from t3 where a between 1 and 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 2 Using where
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 2 Using index condition
# SELECT * FROM tbl_name WHERE <non-indexed vcol expr>
select * from t3 where b between -2 and -1;
a b c
@@ -165,7 +165,7 @@ a b c
1 -1 -1
explain select * from t3 where c between -2 and -1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 2 Using where
+1 SIMPLE t3 range c c 5 NULL 2 Using index condition
# SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <non-indexed vcol>
select * from t3 where a between 1 and 2 order by b;
a b c
@@ -173,7 +173,7 @@ a b c
1 -1 -1
explain select * from t3 where a between 1 and 2 order by b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 2 Using where; Using filesort
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 2 Using index condition; Using filesort
# SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <indexed vcol>
select * from t3 where a between 1 and 2 order by c;
a b c
@@ -181,7 +181,7 @@ a b c
1 -1 -1
explain select * from t3 where a between 1 and 2 order by c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 2 Using where; Using filesort
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 2 Using index condition; Using filesort
# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-vcol>
select * from t3 where b between -2 and -1 order by a;
a b c
@@ -205,7 +205,7 @@ a b c
1 -1 -1
explain select * from t3 where c between -2 and -1 order by b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 2 Using where; Using filesort
+1 SIMPLE t3 range c c 5 NULL 2 Using index condition; Using filesort
# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <indexed vcol>
select * from t3 where b between -2 and -1 order by c;
a b c
@@ -221,7 +221,7 @@ a b c
1 -1 -1
explain select * from t3 where c between -2 and -1 order by c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 2 Using where
+1 SIMPLE t3 range c c 5 NULL 2 Using index condition
# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
select sum(b) from t1 group by b;
sum(b)
diff --git a/mysql-test/suite/vcol/r/vcol_select_myisam.result b/mysql-test/suite/vcol/r/vcol_select_myisam.result
index 4d74d791841..22305a21c43 100644
--- a/mysql-test/suite/vcol/r/vcol_select_myisam.result
+++ b/mysql-test/suite/vcol/r/vcol_select_myisam.result
@@ -44,7 +44,7 @@ a b c
1 -1 -1
explain select * from t3 where c>=-1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 2 Using where
+1 SIMPLE t3 range c c 5 NULL 2 Using index condition
# select_type=SIMPLE, type=ref
select * from t1,t3 where t1.c=t3.c and t3.c=-1;
a b c a b c
@@ -53,7 +53,7 @@ a b c a b c
explain select * from t1,t3 where t1.c=t3.c and t3.c=-1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 const c c 5 const 1
-1 SIMPLE t1 ref c c 5 const 2 Using where
+1 SIMPLE t1 ref c c 5 const 2 Using index condition
# select_type=PRIMARY, type=index,ALL
select * from t1 where b in (select c from t3);
a b c
@@ -141,7 +141,7 @@ a b c
1 -1 -1
explain select * from t3 where c >= -2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 2 Using where
+1 SIMPLE t3 range c c 5 NULL 2 Using index condition
# SELECT * FROM tbl_name WHERE <non-vcol expr>
select * from t3 where a between 1 and 2;
a b c
@@ -149,7 +149,7 @@ a b c
2 -2 -2
explain select * from t3 where a between 1 and 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using index condition
# SELECT * FROM tbl_name WHERE <non-indexed vcol expr>
select * from t3 where b between -2 and -1;
a b c
@@ -165,7 +165,7 @@ a b c
1 -1 -1
explain select * from t3 where c between -2 and -1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 1 Using where
+1 SIMPLE t3 range c c 5 NULL 1 Using index condition
# SELECT * FROM tbl_name WHERE <non-vcol expr> ORDER BY <indexed vcol>
select * from t3 where a between 1 and 2 order by c;
a b c
@@ -173,7 +173,7 @@ a b c
1 -1 -1
explain select * from t3 where a between 1 and 2 order by c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using where; Using filesort
+1 SIMPLE t3 range PRIMARY PRIMARY 4 NULL 1 Using index condition; Using filesort
# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-vcol>
select * from t3 where b between -2 and -1 order by a;
a b c
@@ -189,7 +189,7 @@ a b c
2 -2 -2
explain select * from t3 where c between -2 and -1 order by a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 1 Using where; Using filesort
+1 SIMPLE t3 range c c 5 NULL 1 Using index condition; Using filesort
# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <non-indexed vcol>
select * from t3 where b between -2 and -1 order by b;
a b c
@@ -205,7 +205,7 @@ a b c
1 -1 -1
explain select * from t3 where c between -2 and -1 order by b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 1 Using where; Using filesort
+1 SIMPLE t3 range c c 5 NULL 1 Using index condition; Using filesort
# SELECT * FROM tbl_name WHERE <non-indexed vcol expr> ORDER BY <indexed vcol>
select * from t3 where b between -2 and -1 order by c;
a b c
@@ -221,7 +221,7 @@ a b c
1 -1 -1
explain select * from t3 where c between -2 and -1 order by c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range c c 5 NULL 1 Using where
+1 SIMPLE t3 range c c 5 NULL 1 Using index condition
# SELECT sum(<non-indexed vcol>) FROM tbl_name GROUP BY <non-indexed vcol>
select sum(b) from t1 group by b;
sum(b)
diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test
index c1a9435ef6c..e35aca9b718 100644
--- a/mysql-test/t/derived_view.test
+++ b/mysql-test/t/derived_view.test
@@ -394,7 +394,7 @@ DROP TABLE t1;
--echo # LP bug #803851: materialized view + IN->EXISTS
--echo #
-SET SESSION optimizer_switch='semijoin=off,derived_with_keys=on';
+SET SESSION optimizer_switch='semijoin=off,derived_with_keys=on,materialization=off';
CREATE TABLE t1 (a int, b int);
INSERT INTO t1 VALUES (2,2), (3,3), (1,1);
@@ -895,7 +895,7 @@ INSERT INTO t3 VALUES
(14,4,'a'), (15,7,'b'), (16,4,'c'), (17,1,'d'), (18,9,'e'),
(19,4,'f'), (20,8,'g');
-SET SESSION optimizer_switch='derived_merge=on,subquery_cache=off';
+SET SESSION optimizer_switch='derived_merge=on,subquery_cache=off,materialization=off';
--echo # The following two EXPLAINs must return the same execution plan
EXPLAIN
diff --git a/mysql-test/t/gis-precise.test b/mysql-test/t/gis-precise.test
new file mode 100644
index 00000000000..1de8726a7bc
--- /dev/null
+++ b/mysql-test/t/gis-precise.test
@@ -0,0 +1,312 @@
+-- source include/have_geometry.inc
+
+
+#
+# Spatial objects
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 0,20 20,0 20,0 0))'), GeomFromText('POLYGON((10 10,30 10,30 30,10 30,10 10))'));
+select 0, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 40, 40 50, 20 70, 10 40))'));
+select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POINT(10 10)'));
+select 1, ST_Intersects(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
+select 0, ST_Within(GeomFromText('POLYGON((0 0,20 10,10 30, 0 0))'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
+select 1, ST_Within(GeomFromText('POLYGON((1 1,20 10,10 30, 1 1))'), GeomFromText('POLYGON((0 0,30 5,10 40, 0 0))'));
+
+
+create table t1 (g point);
+insert into t1 values
+(GeomFromText('POINT(2 2)')), (GeomFromText('POINT(2 4)')), (GeomFromText('POINT(2 6)')), (GeomFromText('POINT(2 8)')),
+(GeomFromText('POINT(4 2)')), (GeomFromText('POINT(4 4)')), (GeomFromText('POINT(4 6)')), (GeomFromText('POINT(4 8)')),
+(GeomFromText('POINT(6 2)')), (GeomFromText('POINT(6 4)')), (GeomFromText('POINT(6 6)')), (GeomFromText('POINT(6 8)')),
+(GeomFromText('POINT(8 2)')), (GeomFromText('POINT(8 4)')), (GeomFromText('POINT(8 6)')), (GeomFromText('POINT(8 8)'));
+
+select astext(g) from t1 where ST_Within(g, GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'));
+select 'Contains';
+select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g);
+select 'Intersects';
+select astext(g) from t1 where ST_Intersects(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g);
+select 'Contains';
+select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1))'), g);
+select 'Contains2';
+select astext(g) from t1 where ST_Contains(GeomFromText('POLYGON((5 1, 7 1, 7 7, 5 7, 3 3, 5 3, 5 1), (5.01 3.01, 6 5, 9 5, 8 3, 5.01 3.01))'), g);
+
+DROP TABLE t1;
+
+select 0, ST_Within(GeomFromText('LINESTRING(15 15, 50 50, 60 60)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
+select 1, ST_Within(GeomFromText('LINESTRING(15 15, 16 16)'), GeomFromText('POLYGON((10 10,30 20,20 40, 10 10))'));
+
+
+select 1, ST_Intersects(GeomFromText('LINESTRING(15 15, 50 50)'), GeomFromText('LINESTRING(50 15, 15 50)'));
+select 0, ST_Intersects(GeomFromText('LINESTRING(15 15, 50 50)'), GeomFromText('LINESTRING(16 16, 51 51)'));
+
+select 1, ST_Intersects(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POLYGON((50 5, 55 10, 0 45, 50 5))'));
+
+select astext(ST_Union(geometryfromtext('point(1 1)'), geometryfromtext('polygon((0 0, 2 0, 1 2, 0 0))')));
+select astext(ST_Intersection(geometryfromtext('point(1 1)'), geometryfromtext('polygon((0 0, 2 0, 1 2, 0 0))')));
+
+select ST_Intersects(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POLYGON((50 5, 55 10, 0 45, 50 5))'));
+select ST_contains(GeomFromText('MULTIPOLYGON(((0 0, 0 5, 5 5, 5 0, 0 0)), ((6 6, 6 11, 11 11, 11 6, 6 6)))'), GeomFromText('POINT(5 10)'));
+select ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 15, 15 15, 15 10, 10 10))'));
+select ST_Disjoint(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 4, 4 4, 4 10, 10 10))'));
+select ST_Overlaps(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((10 10, 10 4, 4 4, 4 10, 10 10))'));
+select ST_Overlaps(GeomFromText('POLYGON((0 0, 0 5, 5 5, 5 0, 0 0))'), GeomFromText('POLYGON((1 1, 1 4, 4 4, 4 1, 1 1))'));
+
+# Distance tests
+select ST_DISTANCE(geomfromtext('polygon((0 0, 1 2, 2 1, 0 0))'), geomfromtext('polygon((2 2, 3 4, 4 3, 2 2))'));
+select ST_DISTANCE(geomfromtext('polygon((0 0, 1 2, 2 1, 0 0))'), geomfromtext('linestring(0 1, 1 0)'));
+select ST_DISTANCE(geomfromtext('polygon((0 0, 3 6, 6 3, 0 0))'), geomfromtext('polygon((2 2, 3 4, 4 3, 2 2))'));
+select ST_DISTANCE(geomfromtext('polygon((0 0, 3 6, 6 3, 0 0),(2 2, 3 4, 4 3, 2 2))'), geomfromtext('point(3 3)'));
+select ST_DISTANCE(geomfromtext('linestring(0 0, 3 6, 6 3, 0 0)'), geomfromtext('polygon((2 2, 3 4, 4 3, 2 2))'));
+
+
+# Operations tests
+select astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POLYGON((50 5, 55 10, 0 45, 50 5))')));
+select astext(ST_Intersection(GeomFromText('LINESTRING(0 0, 50 45, 40 50, 0 0)'), GeomFromText('LINESTRING(50 5, 55 10, 0 45, 50 5)')));
+select astext(ST_Intersection(GeomFromText('LINESTRING(0 0, 50 45, 40 50)'), GeomFromText('LINESTRING(50 5, 55 10, 0 45)')));
+select astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('POINT(20 20)')));
+select astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200)')));
+select astext(ST_Intersection(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200, 199 201, -11 -9)')));
+select astext(ST_UNION(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200, 199 201, -11 -9)')));
+
+select astext(ST_intersection(geomfromtext('polygon((0 0, 1 0, 0 1, 0 0))'), geomfromtext('polygon((0 0, 1 1, 0 2, 0 0))')));
+
+select astext(ST_symdifference(geomfromtext('polygon((0 0, 1 0, 0 1, 0 0))'), geomfromtext('polygon((0 0, 1 1, 0 2, 0 0))')));
+select astext(ST_UNION(GeomFromText('POLYGON((0 0, 50 45, 40 50, 0 0))'), GeomFromText('LINESTRING(-10 -10, 200 200, 199 201, -11 -9)')));
+
+# Buffer() tests
+select astext(ST_buffer(geometryfromtext('point(1 1)'), 1));
+create table t1(geom geometrycollection);
+insert into t1 values (geomfromtext('POLYGON((0 0, 10 10, 0 8, 0 0))'));
+insert into t1 values (geomfromtext('POLYGON((1 1, 10 10, 0 8, 1 1))'));
+select astext(geom), area(geom),area(ST_buffer(geom,2)) from t1;
+select astext(ST_buffer(geom,2)) from t1;
+
+set @geom=geomfromtext('LINESTRING(2 1, 4 2, 2 3, 2 5)');
+set @buff=ST_buffer(@geom,1);
+select astext(@buff);
+
+# cleanup
+DROP TABLE t1;
+
+#Touches tests
+select st_touches(geomfromtext('point(0 0)'), geomfromtext('point(1 1)'));
+select st_touches(geomfromtext('point(1 1)'), geomfromtext('point(1 1)'));
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 1)'));
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 0)'));
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('point(1 2)'));
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1.2, 1 0, 2 0, 1 1.2))'));
+select st_touches(geomfromtext('polygon((0 0, 2 2, 0 4, 0 0))'), geomfromtext('polygon((1 1, 1 0, 2 0, 1 1))'));
+
+#Equals test
+SELECT ST_Equals(PolyFromText('POLYGON((67 13, 67 18, 67 18, 59 18, 59 13, 67 13) )'),PolyFromText('POLYGON((67 13, 67 18, 59 19, 59 13, 59 13, 67 13) )')) as result;
+SELECT ST_Equals(PolyFromText('POLYGON((67 13, 67 18, 67 18, 59 18, 59 13, 67 13) )'),PolyFromText('POLYGON((67 13, 67 18, 59 18, 59 13, 59 13, 67 13) )')) as result;
+SELECT ST_Equals(PointFromText('POINT (12 13)'),PointFromText('POINT (12 13)')) as result;
+
+# bug #801243 Assertion `(0)' failed in Gis_geometry_collection::init_from_opresult on ST_UNION
+
+SELECT astext(ST_UNION (
+ PolyFromText('POLYGON(( 2 2 ,3 2,2 7,2 2),( 0 0,8 2,1 9,0 0))'),
+ ExteriorRing( Envelope( MultiLineStringFromText('MULTILINESTRING((3 4,5 3),(3 0,0 5))')))));
+
+#bug 801189 ST_BUFFER asserts if radius = 0
+SELECT astext(ST_BUFFER(LineStringFromText('LINESTRING(0 0,1 1)'),0));
+
+#bug 801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT
+SELECT Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), 3)), 5);
+
+#bug 801212 Assertion with ST_INTERSECTION on NULL values
+SELECT ST_INTERSECTION(NULL, NULL);
+
+#bug 804305 Crash in wkb_get_double with ST_INTERSECTION
+SELECT ASTEXT(ST_INTERSECTION(
+ MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4)),
+ ((0 5,3 5,3 0,0 0,0 1,2 1,2 2,0 2,0 5), (1 3,2 3,2 4,1 4,1 3)),
+ ((2 2,5 2,4 4,2 8,2 2)))'),
+ MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((3 5,2 4,2 5,3 5)),
+ ((2 2,9 2,0 2,2 6,2 2)),
+ ((2 2,2 8,8 8,8 2,2 2), (4 4,4 6,6 6,6 4,4 4)),
+ ((9 9,6 8,7 0,9 9)))')));
+
+#bug 804324 Assertion 0 in Gcalc_scan_iterator::pop_suitable_intersection
+
+SELECT ASTEXT(ST_UNION(
+ MULTILINESTRINGFROMTEXT('MULTILINESTRING((6 2,4 0,3 5,3 6,4 3,6 4,3 9,0 7,3 7,8 4,2 9,5 0),
+ (8 2,1 3,9 0,4 4))'),
+ MULTILINESTRINGFROMTEXT('MULTILINESTRING((2 5,6 7,9 7,5 2,1 6,3 6))')));
+
+SELECT ST_NUMGEOMETRIES((ST_UNION(ST_UNION(
+ MULTILINESTRINGFROMTEXT('MULTILINESTRING((2 0,4 2,0 2,1 5,0 3,7 0,8 5,5 8),
+ (6 2,4 0,3 5,3 6,4 3,6 4,3 9,0 7,3 7,8 4,2 9,5 0),
+ (7 8,3 1,0 9,6 0,4 8),
+ (9 3,0 4,5 9,6 4),
+ (8 2,1 3,9 0,4 4))'),
+ MULTILINESTRINGFROMTEXT('MULTILINESTRING((6 0,9 3,2 5,3 6,3 2),
+ (2 5,6 7,9 7,5 2,1 6,3 6))')),
+ MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((7 7,3 7,3 1,7 8,7 7)),
+ ((3 5,2 4,2 5,3 5)),
+ ((7 7,8 7,3 7,7 7,7 7)),
+ ((0 5,3 5,3 4,1 4,1 3,3 3,3 0,0 0,0 5), (1 1,2 1,2 2,1 2,1 1)))'))));
+
+#bug #805860 Second assertion Assertion `n > 0 && n < SINUSES_CALCULATED*2+1' in get_n_sinco
+
+SELECT Round(ST_AREA(ST_BUFFER( ST_UNION(
+ POLYGONFROMTEXT('POLYGON((7 7, 7 7, 7 4, 7 7, 7 7))'),
+ POLYGONFROMTEXT('POLYGON((7 7, 4 7, 2 9, 7 6, 7 7))')), 1)), 6);
+
+
+#bug #804259 Second assertion in Gis_geometry_collection::init_from_opresult
+
+SELECT AsText(ST_UNION(MultiPolygonFromText('
+ MULTIPOLYGON(((2 2, 2 8, 8 8, 8 2, 2 2), (4 4, 4 6, 6 6, 6 4, 4 4)),
+ ((0 0, 8 3, 7 4, 0 0)),
+ ((2 2, 2 8, 8 8, 8 2, 2 2), (4 4, 4 6, 6 6, 6 4, 4 4)))'),
+MultiPolygonFromText(' MULTIPOLYGON(((0 0, 1 9, 4 6, 0 0)),
+ ((0 5, 3 5, 3 4, 1 4, 1 3, 3 3, 3 0, 0 0, 0 5), (1 1, 2 1, 2 2, 1 2, 1 1)),
+ ((7 7, 4 7, 6 3, 7 2, 7 7)),
+ ((0 5, 3 5, 3 4, 1 4, 1 3, 3 3, 3 0, 0 0, 0 5), (1 1, 2 1, 2 2, 1 2, 1 1))) ')));
+
+
+#bug 801217 Assertion `t1->result_range' in Gcalc_operation_reducer::end_couple
+
+SELECT AsText(ST_SYMDIFFERENCE(
+ MultiLineStringFromText('MULTILINESTRING((7 7, 1 7, 8 5, 7 8, 7 7),
+ (6 3, 3 4, 1 1, 9 9, 9 0, 8 4, 9 9))'),
+ Envelope(GeometryFromText('MULTIPOINT(7 9, 0 0, 3 7, 1 6, 0 0)'))));
+
+#bug 804266 Memory corruption/valgrind warning/crash in move_hole() with ST_UNION
+
+SELECT AsText(ST_UNION(
+ MultiPolygonFromText('MULTIPOLYGON(((9 9, 7 9, 1 1, 9 9)),
+ ((2 2, 1 2, 3 3, 2 2, 2 2)),
+ ((0 0, 7 5, 9 6, 0 0)),
+ ((7 7, 5 7, 1 5, 7 1, 7 7)))'),
+ MultiPolygonFromText('MULTIPOLYGON(((2 2, 2 2, 1 5, 2 7, 2 2)),
+ ((0 5, 3 5, 3 0, 0 0, 0 5), (1 1, 2 1, 2 4, 1 4, 1 1)))')));
+
+#bug 802376 ST_INTERSECTION returns wrong result on two overlapping linestrings in maria-5.3-gis
+
+SELECT AsText( ST_INTERSECTION(
+ LinestringFromText('LINESTRING( 3 5, 2 5, 2 4, 3 4, 3 5 ) ') ,
+ LinestringFromText('LINESTRING( 3 5, 2 4, 2 5, 3 5 ) ')
+));
+
+#bug 801560 ST_UNION of adjacent polygons includes extra line in maria-5.3-gis
+
+SELECT AsText( ST_UNION(
+ PolygonFromText(' POLYGON( ( 2 2 , 3 2 , 7 5 , 2 0 , 2 2 ) ) ') ,
+ PolygonFromText(' POLYGON( ( 2 2 , 3 2 , 3 3 , 2 5 , 2 2 ) ) ') ) );
+
+#bug 801466 ST_INTERSECTION() returns invalid value on empty intersection in maria-5.3-gis
+
+SELECT AsText(ST_INTERSECTION(LinestringFromText('LINESTRING(1 1, 2 2)'), GeometryFromText('LINESTRING(3 3, 4 4)')));
+
+#bug 839341 100% CPU usage with ST_UNION in maria-5.3-gis
+SELECT AsText(ST_UNION(GEOMETRYFROMTEXT('POINT(8 1)') ,MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 5, 2 5, 2 4, 3 4, 3 5))')));
+
+#bug 839318 Crash in Gcalc_scan_iterator::point::get_shape with ST_DISTANCE and MULTILINESTRING in maria-5.3-gis
+SELECT ST_DISTANCE(POINTFROMTEXT('POINT(7 1)'),MULTILINESTRINGFROMTEXT('MULTILINESTRING(
+ (4 7,9 7,6 1,3 4,1 1), (3 5, 2 5, 2 4, 3 4, 3 5))'));
+
+#bug 839327 Crash in Gcalc_operation_reducer::end_couple with ST_UNION and MULTIPOLYGONs in 5.3-gis
+SELECT AsText(ST_UNION(POLYGONFROMTEXT('POLYGON((12 9, 3 6, 3 0, 12 9))'), POLYGONFROMTEXT('POLYGON((2 2, 7 2, 4 2, 2 0, 2 2))')));
+
+#bug 841622 Assertion `t->rp->type == Gcalc_function::shape_line' failed in Gcalc_operation_reducer::end_line in maria-5.3-gis
+
+SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER(ST_UNION(
+ MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 2 5, 7 6, 1 8),(0 0 ,1 6 ,0 1, 8 9, 2 4, 6 1, 3 5, 4 8), (9 3, 5 4, 1 8, 4 2, 5 8, 3 0))' ) ,
+ MULTILINESTRINGFROMTEXT('MULTILINESTRING((3 4, 3 1, 2 7, 4 2, 6 2, 1 5))')
+ ), 16)));
+
+#bug 841625 Assertion `m_poly_borders->next' failed in Gcalc_operation_reducer::count_slice in maria-5.3-gis
+
+SELECT ST_NUMGEOMETRIES(ST_DIFFERENCE (
+ ST_UNION (
+ MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 4 , 5 0 , 2 9 , 6 2 , 0 2 ) , ( 4 3 , 5 6 , 9 4 , 0 7 , 7 2 , 2 0 , 8 2 ) , ( 5 0 , 1 5 , 3 7 , 7 7 ) , ( 2 3 , 9 5 , 2 0 , 8 1 ) , ( 0 9 , 9 3 , 2 8 , 8 1 , 9 4 ) ) ' ),
+ ST_UNION (
+ MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 7 2 , 6 2 , 2 6 , 2 2 ) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) ,
+ ENVELOPE(
+ MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' )
+ )
+ )
+ ),
+ MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 2 9 , 1 3 , 7 3 , 8 5 ) , ( 5 0 , 8 1 , 2 0 , 7 4 , 1 0 ) , ( 9 2 , 5 2 , 6 5 , 8 8 , 0 2 ) , ( 0 8 , 3 9 , 4 0 , 1 0 ) , ( 0 0 , 7 6 , 8 3 , 0 0 ) ) ' )
+));
+
+
+#bug 841745 ssertion `!sp0->is_bottom()' failed in Gcalc_scan_iterator::find_intersections in maria-5.3-gis
+SELECT ASTEXT(ST_DIFFERENCE (
+ POLYGONFROMTEXT( ' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ' ) ,
+ ST_UNION (
+ MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ' ) ,
+ ST_SYMDIFFERENCE (
+ MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 3 8 , 0 8 , 6 6 , 6 1 , 0 5 , 6 7 , 3 7 ) , ( 5 8 , 7 7 , 9 0 , 8 7 ) , ( 1 5 , 1 8 , 2 3 , 3 9 ) , ( 1 3 , 9 7 , 5 5 , 0 8 , 6 9 ) , ( 3 6 , 6 9 , 8 7 , 0 2 , 4 6 , 9 5 ) ) ' ) ,
+ ST_UNION (
+ MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 9 4 , 2 0 , 2 2 , 7 2 , 6 2 ) , ( 5 2 , 8 2 , 4 8 , 3 4 ) , ( 1 0 , 1 4 , 2 7 , 7 0 , 1 5 ) , ( 2 8 , 4 4 , 5 0 , 7 0 , 4 0 ) ) ' ) ,
+ GEOMETRYFROMTEXT( ' MULTILINESTRING( ( 3 7 , 7 3 , 5 8 , 4 8 ) , ( 3 2 , 5 0 , 9 3 , 4 4 ) , ( 6 0 , 4 2 , 7 8 , 1 3 ) ) ' )
+ )
+ )
+ )
+));
+
+#bug 841773 Assertion `t0->rp->type == t1->rp->type' failed in Gcalc_operation_reducer::end_couple in maria-5.3-gis
+SELECT ST_NUMGEOMETRIES(ST_UNION (
+ MULTILINESTRINGFROMTEXT( ' MULTILINESTRING( ( 0 8 , 1 9 , 5 7 , 2 8 , 5 8 , 6 7 ) , ( 4 5 , 8 4 , 0 3 , 5 1 ) , ( 6 8 , 2 7 , 1 6 , 9 9 , 7 2 ) , ( 9 5 , 2 8 , 1 2 , 9 6 , 2 0 ) ) ' ) ,
+ MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 7 7 , 2 7, 6 8, 7 1 , 7 7 ) ) ) ' )
+));
+
+#bug 841662 Third assertion `n > 0 && n < SINUSES_CALCULATED*2+1' in get_n_sincos
+SELECT ST_BUFFER (
+ LINESTRINGFROMTEXT( ' LINESTRING( 5 4 , 3 8 , 2 6 , 5 5 , 7 9 ) ' ) ,
+ ST_DISTANCE (
+ MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ,
+ ST_DIFFERENCE (
+ MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) ,
+ MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' )
+ )
+ )
+ ) ;
+SELECT ST_DISTANCE ( ST_DIFFERENCE ( MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 5, 2 4, 3 4, 3 5) ) ) ' ) , MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) , ( ( 0 0 , 3 8 , 9 4 , 0 0 ) ) ) ' ) ), MULTIPOLYGONFROMTEXT( ' MULTIPOLYGON( ( (3 5, 2 4, 2 5, 3 5) ) , ( (3 5, 2 5, 2 4, 3 4, 3 5) ) , ( ( 0 0 , 8 3 , 9 5 , 0 0 ) ) ) ' ) ) ;
+
+#bug 848939 Wrong result with ST_INTERSECTION between linestrings and a polygon in 5.3-gis
+SELECT ASTEXT(ST_INTERSECTION( GEOMETRYFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(7 7,5.33333333333333 7),LINESTRING(5.33333333333333 7,0 7,5 8,5.33333333333333 7),LINESTRING(5.33333333333333 7,7 2,7 7),POLYGON((0 5,3 5,3 2,1 2,1 1,3 1,3 0,0 0,0 3,2 3,2 4,0 4,0 5)))'), geomETRYFROMTEXT(' MULTILINESTRING( ( 5 1 , 3 7 , 6 1 , 7 0 ) , ( 1 6 , 8 5 , 7 5 , 5 6 ) )') ));
+
+#bug 855485 ST_CROSSES returns different result than PostGIS for overlapping polygons
+
+SELECT ST_CROSSES( GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 4, 2 5, 3 5) ) ') , POLYGONFROMTEXT(' POLYGON((2 4,3 4,3 5,2 5,2 4)) '));
+
+#bug 855487 ST_WITHIN returns wrong result for partially overlapping polygons
+
+SELECT ST_WITHIN( POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 2 0 , 1 0, 2 4 , 0 4, 0 5) ) ') , POLYGONFROMTEXT(' POLYGON( (0 5, 3 5, 3 4, 1 4 , 1 3 , 3 3 , 3 0 , 0 0 , 0 5), ( 1 1 , 2 1 , 2 2 , 1 2 , 1 1 ) ) ') );
+
+#bug 855492 ST_WITHIN returns TRUE on point on the edge of a polygon
+
+SELECT ST_WITHIN( POINTFROMTEXT(' POINT(1 2 ) ') , MULTIPOLYGONFROMTEXT(' MULTIPOLYGON( ( (0 5, 3 5, 3 0, 0 0, 0 5), ( 1 1 , 2 1 , 2 4, 1 4, 1 1 ) ) ) '));
+
+#bug 855497 ST_ENVELOPE of GEOMETRYCOLLECTION EMPTY returns NULL and not GEOMETRYCOLLECTION EMPTY
+
+select ST_ASTEXT(envelope(ST_GEOMCOLLFROMTEXT('GEOMETRYCOLLECTION EMPTY')));
+
+#bug 855503 ST_EQUALS reports TRUE between a POLYGON and a MULTILINESTRING
+
+SELECT ST_EQUALS( GEOMETRYFROMTEXT(' MULTILINESTRING( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') , GEOMETRYFROMTEXT(' POLYGON( (3 5, 2 5, 2 4, 3 4, 3 5) ) ') );
+
+#bug 855505 ST_TOUCHES reports TRUE for intersecting polygon and linestring
+
+SELECT ST_TOUCHES( GEOMETRYFROMTEXT(' LINESTRING( 1 1 , 1 4 , 5 0 , 8 3 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) ') );
+
+#bug 857051 ST_EQUALS returns TRUE on two nonidentical MULTIPOINTs
+
+SELECT ST_EQUALS( MULTIPOINTFROMTEXT(' MULTIPOINT( 5 1 , 6 9 , 1 4 , 4 0 ) ') , MULTIPOINTFROMTEXT(' MULTIPOINT( 5 8 , 5 2 , 1 8 , 3 0 , 3 0 , 7 8 ) ') );
+SELECT ST_EQUALS( MULTIPOINTFROMTEXT(' MULTIPOINT( 5 1 , 6 9 , 1 4 , 4 0 ) ') , MULTIPOINTFROMTEXT('MULTIPOINT( 4 0 , 6 9 , 5 1, 1 4 )') );
+
+#bug 857050 ST_WITHIN returns wrong result with MULTIPOINT and POLYGON
+SELECT ST_WITHIN( MULTIPOINTFROMTEXT(' MULTIPOINT( 2 9 , 2 9 , 4 9 , 9 1 ) ') , POLYGONFROMTEXT(' POLYGON( ( 2 2 , 2 8 , 8 8 , 8 2 , 2 2 ) , ( 4 4 , 4 6 , 6 6 , 6 4 , 4 4 ) ) '));
+
+#bug 857087 Wrong result with ST_INTERSECTS and LINESTRINGs
+
+SELECT ST_INTERSECTS( GeomFromText('MULTILINESTRING( ( 4030 3045 , 3149 2461 , 3004 3831 , 3775 2976 ) )') , GeomFromText('LINESTRING(3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29,3039.07 3175.05,3039.07 3175.05,3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29)') );
+
diff --git a/mysql-test/t/gis-rt-precise.test b/mysql-test/t/gis-rt-precise.test
new file mode 100644
index 00000000000..4cae10a9076
--- /dev/null
+++ b/mysql-test/t/gis-rt-precise.test
@@ -0,0 +1,64 @@
+-- source include/have_geometry.inc
+
+#
+# test of rtree (using with spatial data)
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (
+ fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ g GEOMETRY NOT NULL,
+ SPATIAL KEY(g)
+) ENGINE=MyISAM;
+
+SHOW CREATE TABLE t1;
+
+--disable_query_log
+let $1=150;
+let $2=150;
+while ($1)
+{
+ eval INSERT INTO t1 (g) VALUES (GeomFromText('LineString($1 $1, $2 $2)'));
+ dec $1;
+ inc $2;
+}
+--enable_query_log
+
+SELECT count(*) FROM t1;
+EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE ST_Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 140))'));
+SELECT fid, AsText(g) FROM t1 WHERE ST_Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
+
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ g GEOMETRY NOT NULL
+) ENGINE=MyISAM;
+
+--disable_query_log
+let $1=10;
+while ($1)
+{
+ let $2=10;
+ while ($2)
+ {
+ eval INSERT INTO t1 (g) VALUES (LineString(Point($1 * 10 - 9, $2 * 10 - 9), Point($1 * 10, $2 * 10)));
+ dec $2;
+ }
+ dec $1;
+}
+--enable_query_log
+
+ALTER TABLE t1 ADD SPATIAL KEY(g);
+SHOW CREATE TABLE t1;
+SELECT count(*) FROM t1;
+EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE ST_Within(g,
+ GeomFromText('Polygon((40 40,60 40,60 60,40 40))'));
+SELECT fid, AsText(g) FROM t1 WHERE ST_Within(g,
+ GeomFromText('Polygon((40 40,60 40,60 60,40 40))'));
+
+DROP TABLE t1;
+
+--echo End of 5.5 tests.
diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test
index b99d35ecd48..e7e6fa59df0 100644
--- a/mysql-test/t/gis-rtree.test
+++ b/mysql-test/t/gis-rtree.test
@@ -17,16 +17,12 @@ SHOW CREATE TABLE t1;
let $1=150;
let $2=150;
---disable_query_log
-begin;
while ($1)
{
eval INSERT INTO t1 (g) VALUES (GeomFromText('LineString($1 $1, $2 $2)'));
dec $1;
inc $2;
}
-commit;
---enable_query_log
SELECT count(*) FROM t1;
EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
@@ -39,8 +35,6 @@ CREATE TABLE t2 (
g GEOMETRY NOT NULL
) ENGINE=MyISAM;
---disable_query_log
-begin;
let $1=10;
while ($1)
{
@@ -52,8 +46,6 @@ while ($1)
}
dec $1;
}
-commit;
---enable_query_log
ALTER TABLE t2 ADD SPATIAL KEY(g);
SHOW CREATE TABLE t2;
@@ -63,8 +55,6 @@ EXPLAIN SELECT fid, AsText(g) FROM t2 WHERE Within(g,
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
---disable_query_log
-begin;
let $1=10;
while ($1)
{
@@ -77,8 +67,6 @@ while ($1)
}
dec $1;
}
-commit;
---enable_query_log
DROP TABLE t2;
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index 104afddeee5..202e4f88cd8 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -62,7 +62,9 @@ INSERT INTO gis_multi_polygon VALUES
INSERT INTO gis_geometrycollection VALUES
(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')),
-(121, GeometryFromWKB(AsWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))));
+(121, GeometryFromWKB(AsWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))))),
+(122, GeomFromText('GeometryCollection()')),
+(123, GeomFromText('GeometryCollection EMPTY'));
INSERT into gis_geometry SELECT * FROM gis_point;
INSERT into gis_geometry SELECT * FROM gis_line;
@@ -539,18 +541,6 @@ insert into t1 values(default);
drop table t1;
#
-# Bug #27300: create view with geometry functions lost columns types
-#
-CREATE TABLE t1 (a GEOMETRY);
-CREATE VIEW v1 AS SELECT GeomFromwkb(ASBINARY(a)) FROM t1;
-CREATE VIEW v2 AS SELECT a FROM t1;
-DESCRIBE v1;
-DESCRIBE v2;
-
-DROP VIEW v1,v2;
-DROP TABLE t1;
-
-#
# Bug#24563: MBROverlaps does not seem to function propertly
# Bug#54888: MBROverlaps missing in 5.1?
#
@@ -773,14 +763,7 @@ drop table t1;
#
# Bug #50574 5.5.x allows spatial indexes on non-spatial
# columns, causing crashes!
-# Bug#11767480 SPATIAL INDEXES ON NON-SPATIAL COLUMNS
-# CAUSE CRASHES.
#
-CREATE TABLE t0 (a BINARY(32) NOT NULL);
---error ER_SPATIAL_MUST_HAVE_GEOM_COL
-CREATE SPATIAL INDEX i on t0 (a);
-INSERT INTO t0 VALUES (1);
-
--error ER_SPATIAL_MUST_HAVE_GEOM_COL
CREATE TABLE t1(
col0 BINARY NOT NULL,
@@ -818,7 +801,542 @@ CREATE TABLE t3 (
);
# cleanup
-DROP TABLE t0, t1, t2;
+DROP TABLE t1;
+DROP TABLE t2;
+
+#bug 850775 ST_AREA does not work on GEOMETRYCOLLECTIONs in maria-5.3-gis
+select ST_AREA(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))'));
+
+#bug 855336 ST_LENGTH does not work on GEOMETRYCOLLECTIONs
+select ST_LENGTH(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 100 30, 20 30), POINT(3 3), LINESTRING(20 20, 30 20))'));
+
+
+# Conformance tests
+#
+# C.3.3 Geometry types and functions
+#
+
+--disable_warnings
+DROP DATABASE IF EXISTS gis_ogs;
+--enable_warnings
+
+CREATE DATABASE gis_ogs;
+USE gis_ogs;
+
+--echo #
+--echo # C.3.3.1 Geometry types and functions schema construction
+--echo #
+
+# TODO: WL#2377
+#CREATE TABLE spatial_ref_sys (
+#srid INTEGER NOT NULL PRIMARY KEY,
+#auth_name CHARACTER VARYING,
+#auth_srid INTEGER,
+#srtext CHARACTER VARYING(2048));
+
+CREATE TABLE lakes (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ name CHARACTER VARYING(64),
+ shore POLYGON);
+
+CREATE TABLE road_segments (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ name CHARACTER VARYING(64),
+ aliases CHARACTER VARYING(64),
+ num_lanes INTEGER,
+ centerline LINESTRING);
+
+CREATE TABLE divided_routes (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ name CHARACTER VARYING(64),
+ num_lanes INTEGER,
+ centerlines MULTILINESTRING);
+
+CREATE TABLE forests (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ name CHARACTER VARYING(64),
+ boundary MULTIPOLYGON);
+
+CREATE TABLE bridges (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ name CHARACTER VARYING(64),
+ position POINT);
+
+CREATE TABLE streams (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ name CHARACTER VARYING(64),
+ centerline LINESTRING);
+
+CREATE TABLE buildings (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ address CHARACTER VARYING(64),
+ position POINT,
+ footprint POLYGON);
+
+CREATE TABLE ponds (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ name CHARACTER VARYING(64),
+ type CHARACTER VARYING(64),
+ shores MULTIPOLYGON);
+
+CREATE TABLE named_places (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ name CHARACTER VARYING(64),
+ boundary POLYGON);
+
+CREATE TABLE map_neatlines (
+ fid INTEGER NOT NULL PRIMARY KEY,
+ neatline POLYGON);
+
+--echo #
+--echo # C.3.3.2 Geometry types and functions schema data loading
+--echo #
+
+# TODO: WL#2377
+#-- Spatial Reference System
+#INSERT INTO spatial_ref_sys VALUES
+#(101, 'POSC', 32214, 'PROJCS["UTM_ZONE_14N",
+#GEOGCS["World Geodetic System 72",
+#DATUM["WGS_72",
+#ELLIPSOID["NWL_10D", 6378135, 298.26]],
+#PRIMEM["Greenwich", 0],
+#UNIT["Meter", 1.0]],
+#PROJECTION["Transverse_Mercator"],
+#PARAMETER["False_Easting", 500000.0],
+#PARAMETER["False_Northing", 0.0],
+#PARAMETER["Central_Meridian", -99.0],
+#PARAMETER["Scale_Factor", 0.9996],
+#PARAMETER["Latitude_of_origin", 0.0],
+#UNIT["Meter", 1.0]]');
+
+--echo # Lakes
+INSERT INTO lakes VALUES (
+101, 'BLUE LAKE',
+PolyFromText(
+'POLYGON(
+(52 18,66 23,73 9,48 6,52 18),
+(59 18,67 18,67 13,59 13,59 18)
+)',
+101));
+
+
+--echo # Road Segments
+
+INSERT INTO road_segments VALUES(102, 'Route 5', NULL, 2,
+LineFromText(
+'LINESTRING( 0 18, 10 21, 16 23, 28 26, 44 31 )' ,101));
+
+INSERT INTO road_segments VALUES(103, 'Route 5', 'Main Street', 4,
+LineFromText(
+'LINESTRING( 44 31, 56 34, 70 38 )' ,101));
+
+INSERT INTO road_segments VALUES(104, 'Route 5', NULL, 2,
+LineFromText(
+'LINESTRING( 70 38, 72 48 )' ,101));
+
+INSERT INTO road_segments VALUES(105, 'Main Street', NULL, 4,
+LineFromText(
+'LINESTRING( 70 38, 84 42 )' ,101));
+
+INSERT INTO road_segments VALUES(106, 'Dirt Road by Green Forest', NULL,
+1,
+LineFromText(
+'LINESTRING( 28 26, 28 0 )',101));
+
+--echo # DividedRoutes
+
+INSERT INTO divided_routes VALUES(119, 'Route 75', 4,
+MLineFromText(
+'MULTILINESTRING((10 48,10 21,10 0),
+(16 0,16 23,16 48))', 101));
+
+--echo # Forests
+
+INSERT INTO forests VALUES(109, 'Green Forest',
+MPolyFromText(
+'MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),
+(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))',
+101));
+
+--echo # Bridges
+
+INSERT INTO bridges VALUES(110, 'Cam Bridge', PointFromText(
+'POINT( 44 31 )', 101));
+
+--echo # Streams
+
+INSERT INTO streams VALUES(111, 'Cam Stream',
+LineFromText(
+'LINESTRING( 38 48, 44 41, 41 36, 44 31, 52 18 )', 101));
+
+INSERT INTO streams VALUES(112, NULL,
+LineFromText(
+'LINESTRING( 76 0, 78 4, 73 9 )', 101));
+
+--echo # Buildings
+
+INSERT INTO buildings VALUES(113, '123 Main Street',
+PointFromText(
+'POINT( 52 30 )', 101),
+PolyFromText(
+'POLYGON( ( 50 31, 54 31, 54 29, 50 29, 50 31) )', 101));
+
+INSERT INTO buildings VALUES(114, '215 Main Street',
+PointFromText(
+'POINT( 64 33 )', 101),
+PolyFromText(
+'POLYGON( ( 66 34, 62 34, 62 32, 66 32, 66 34) )', 101));
+
+
+--echo # Ponds
+
+INSERT INTO ponds VALUES(120, NULL, 'Stock Pond',
+MPolyFromText(
+'MULTIPOLYGON( ( ( 24 44, 22 42, 24 40, 24 44) ),
+( ( 26 44, 26 40, 28 42, 26 44) ) )', 101));
+
+--echo # Named Places
+
+INSERT INTO named_places VALUES(117, 'Ashton',
+PolyFromText(
+'POLYGON( ( 62 48, 84 48, 84 30, 56 30, 56 34, 62 48) )', 101));
+
+INSERT INTO named_places VALUES(118, 'Goose Island',
+PolyFromText(
+'POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )', 101));
+
+--echo # Map Neatlines
+
+INSERT INTO map_neatlines VALUES(115,
+PolyFromText(
+'POLYGON( ( 0 0, 0 48, 84 48, 84 0, 0 0 ) )', 101));
+
+--echo #
+--echo # C.3.3.3 Geometry types and functions schema test queries
+--echo
+
+# TODO: WL#2377
+#--echo # Conformance Item T1
+#SELECT f_table_name
+#FROM geometry_columns;
+#
+#--echo # Conformance Item T2
+#SELECT f_geometry_column
+#FROM geometry_columns
+#WHERE f_table_name = 'streams';
+#
+#--echo # Conformance Item T3
+#SELECT coord_dimension
+#FROM geometry_columns
+#WHERE f_table_name = 'streams';
+#
+#--echo # Conformance Item T4
+#
+#SELECT srid
+#FROM geometry_columns
+#WHERE f_table_name = 'streams';
+#
+#--echo # Conformance Item T5
+#
+#SELECT srtext
+#FROM SPATIAL_REF_SYS
+#WHERE SRID = 101;
+#
+
+
+--echo # Conformance Item T6
+# TODO: ST_Dimension() alias
+SELECT Dimension(shore)
+FROM lakes
+WHERE name = 'Blue Lake';
+
+--echo # Conformance Item T7
+# TODO: ST_GeometryType() alias
+SELECT GeometryType(centerlines)
+FROM divided_routes
+WHERE name = 'Route 75';
+
+--echo # Conformance Item T8
+# TODO: ST_AsText() alias
+SELECT AsText(boundary)
+FROM named_places
+WHERE name = 'Goose Island';
+
+--echo # Conformance Item T9
+# TODO: ST_AsBinary(), ST_PolyFromWKB() aliases
+SELECT AsText(PolyFromWKB(AsBinary(boundary),101))
+FROM named_places
+WHERE name = 'Goose Island';
+
+--echo # Conformance Item T10
+# TODO: ST_SRID() alias
+SELECT SRID(boundary)
+FROM named_places
+WHERE name = 'Goose Island';
+
+--echo # Conformance Item T11
+# TODO: ST_IsEmpty() alias
+SELECT IsEmpty(centerline)
+FROM road_segments
+WHERE name = 'Route 5'
+AND aliases = 'Main Street';
+
+# FIXME: get wrong result:0, expected 1.
+#--echo # Conformance Item T12
+# TODO: ST_IsSimple() alias
+#SELECT IsSimple(shore)
+#FROM lakes
+#WHERE name = 'Blue Lake';
+
+# TODO: WL#2377
+#--echo # Conformance Item T13
+#SELECT AsText(Boundary((boundary),101)
+#FROM named_places
+#WHERE name = 'Goose Island';
+
+--echo # Conformance Item T14
+# TODO: ST_Envelope( ) alias
+# FIXME: we get anticlockwise, GIS suggests clockwise
+SELECT AsText(Envelope(boundary))
+FROM named_places
+WHERE name = 'Goose Island';
+
+--echo # Conformance Item T15
+# TODO: ST_X() alias
+SELECT X(position)
+FROM bridges
+WHERE name = 'Cam Bridge';
+
+--echo # Conformance Item T16
+# TODO: ST_Y() alias
+SELECT Y(position)
+FROM bridges
+WHERE name = 'Cam Bridge';
+
+--echo # Conformance Item T17
+# TODO: ST_StartPoint() alias
+SELECT AsText(StartPoint(centerline))
+FROM road_segments
+WHERE fid = 102;
+
+--echo # Conformance Item T18
+# TODO: ST_EndPoint
+SELECT AsText(EndPoint(centerline))
+FROM road_segments
+WHERE fid = 102;
+
+# TODO: WL#2377
+#--echo # Conformance Item T19
+# TODO: ST_LineFromWKB() alias
+#SELECT IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
+#FROM named_places
+#WHERE name = 'Goose Island';
+
+# TODO: WL#2377
+#--echo # Conformance Item T20
+#SELECT IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
+#FROM named_places
+#WHERE name = 'Goose Island';
+
+--echo # Conformance Item T21
+# TODO: ST_Length() alias
+SELECT GLength(centerline)
+FROM road_segments
+WHERE fid = 106;
+
+--echo # Conformance Item T22
+# TODO: ST_NumPoints() alias
+SELECT NumPoints(centerline)
+FROM road_segments
+WHERE fid = 102;
+
+--echo # Conformance Item T23
+# TODO: ST_PointN() alias
+SELECT AsText(PointN(centerline, 1))
+FROM road_segments
+WHERE fid = 102;
+
+--echo # Conformance Item T24
+# TODO: ST_Centroid() alias
+SELECT AsText(Centroid(boundary))
+FROM named_places
+WHERE name = 'Goose Island';
+
+# TODO: WL#2377
+#--echo # Conformance Item T25
+#SELECT Contains(boundary, PointOnSurface(boundary))
+#FROM named_places
+#WHERE name = 'Goose Island';
+
+--echo # Conformance Item T26
+# TODO: ST_Area() alias
+SELECT Area(boundary)
+FROM named_places
+WHERE name = 'Goose Island';
+
+--echo # Conformance Item T27
+# TODO: ST_ExteriorRing() alias
+SELECT AsText(ExteriorRing(shore))
+FROM lakes
+WHERE name = 'Blue Lake';
+
+--echo # Conformance Item T28
+# TODO: ST_NumInteriorRings() alias
+SELECT NumInteriorRings(shore)
+FROM lakes
+WHERE name = 'Blue Lake';
+
+--echo # Conformance Item T29
+# TODO: ST_InteriorRingN() alias
+SELECT AsText(InteriorRingN(shore, 1))
+FROM lakes
+WHERE name = 'Blue Lake';
+
+--echo # Conformance Item T30
+# TODO: ST_NumGeometries() alias
+SELECT NumGeometries(centerlines)
+FROM divided_routes
+WHERE name = 'Route 75';
+
+--echo # Conformance Item T31
+# TODO: ST_GeometryN() alias
+SELECT AsText(GeometryN(centerlines, 2))
+FROM divided_routes
+WHERE name = 'Route 75';
+
+--echo # Conformance Item T32
+# TODO: ST_IsClosed() alias
+SELECT IsClosed(centerlines)
+FROM divided_routes
+WHERE name = 'Route 75';
+
+--echo # Conformance Item T33
+# TODO: ST_Length() alias
+SELECT GLength(centerlines)
+FROM divided_routes
+WHERE name = 'Route 75';
+
+--echo # Conformance Item T34
+# TODO: ST_Centroid() alias
+SELECT AsText(Centroid(shores))
+FROM ponds
+WHERE fid = 120;
+
+# TODO: WL#2377
+#--echo # Conformance Item T35
+#SELECT Contains(shores, PointOnSurface(shores))
+#FROM ponds
+#WHERE fid = 120;
+
+--echo # Conformance Item T36
+# TODO: ST_Area() alias
+SELECT Area(shores)
+FROM ponds
+WHERE fid = 120;
+
+--echo # Conformance Item T37
+# TODO: ST_PolyFromText() alias
+SELECT ST_Equals(boundary,
+PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1))
+FROM named_places
+WHERE name = 'Goose Island';
+
+--echo # Conformance Item T38
+SELECT ST_Disjoint(centerlines, boundary)
+FROM divided_routes, named_places
+WHERE divided_routes.name = 'Route 75'
+AND named_places.name = 'Ashton';
+
+--echo # Conformance Item T39
+SELECT ST_Touches(centerline, shore)
+FROM streams, lakes
+WHERE streams.name = 'Cam Stream'
+AND lakes.name = 'Blue Lake';
+
+# FIXME: wrong result: get 0, expected 1
+#--echo # Conformance Item T40
+#SELECT ST_Within(boundary, footprint)
+#FROM named_places, buildings
+#WHERE named_places.name = 'Ashton'
+#AND buildings.address = '215 Main Street';
+
+# FIXME: wrong result: get 0, expected 1
+#--echo # Conformance Item T41
+#SELECT ST_Overlaps(forests.boundary, named_places.boundary)
+#FROM forests, named_places
+#WHERE forests.name = 'Green Forest'
+#AND named_places.name = 'Ashton';
+
+--echo # Conformance Item T42
+# FIXME: TODO: ST_Crosses() alias
+SELECT Crosses(road_segments.centerline, divided_routes.centerlines)
+FROM road_segments, divided_routes
+WHERE road_segments.fid = 102
+AND divided_routes.name = 'Route 75';
+
+--echo # Conformance Item T43
+SELECT ST_Intersects(road_segments.centerline, divided_routes.centerlines)
+FROM road_segments, divided_routes
+WHERE road_segments.fid = 102
+AND divided_routes.name = 'Route 75';
+
+--echo # Conformance Item T44
+SELECT ST_Contains(forests.boundary, named_places.boundary)
+FROM forests, named_places
+WHERE forests.name = 'Green Forest'
+AND named_places.name = 'Ashton';
+
+# TODO: WL#2377
+#--echo # Conformance Item T45
+#SELECT Relate(forests.boundary, named_places.boundary, 'TTTTTTTTT')
+#FROM forests, named_places
+#WHERE forests.name = 'Green Forest'
+#AND named_places.name = 'Ashton';
+
+--echo # Conformance Item T46
+SELECT ST_Distance(position, boundary)
+FROM bridges, named_places
+WHERE bridges.name = 'Cam Bridge'
+AND named_places.name = 'Ashton';
+
+# FIXME: wrong result: NULL, expected 12
+#--echo # Conformance Item T47
+#SELECT AsText(ST_Intersection(centerline, shore))
+#FROM streams, lakes
+#WHERE streams.name = 'Cam Stream'
+#AND lakes.name = 'Blue Lake';
+
+--echo # Conformance Item T48
+SELECT AsText(ST_Difference(named_places.boundary, forests.boundary))
+FROM named_places, forests
+WHERE named_places.name = 'Ashton'
+AND forests.name = 'Green Forest';
+
+#--echo # Conformance Item T49
+SELECT AsText(ST_Union(shore, boundary))
+FROM lakes, named_places
+WHERE lakes.name = 'Blue Lake'
+AND named_places.name = 'Goose Island';
+
+--echo # Conformance Item T50
+SELECT AsText(ST_SymDifference(shore, boundary))
+FROM lakes, named_places
+WHERE lakes.name = 'Blue Lake'
+AND named_places.name = 'Ashton';
+
+--echo # Conformance Item T51
+SELECT count(*)
+FROM buildings, bridges
+WHERE ST_Contains(ST_Buffer(bridges.position, 15.0), buildings.footprint) = 1;
+
+# TODO: WL#2377
+#--echo # Conformance Item T52
+#SELECT AsText(ConvexHull(shore))
+#FROM lakes
+#WHERE lakes.name = 'Blue Lake';
+
+DROP DATABASE gis_ogs;
+USE test;
--echo #
--echo # Bug#11908153: CRASH AND/OR VALGRIND ERRORS IN FIELD_BLOB::GET_KEY_IMAGE
@@ -838,5 +1356,5 @@ FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month)
DROP TABLE g1;
-
--echo End of 5.5 tests
+
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 18329a1aa75..e660c017854 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -3379,3 +3379,31 @@ execute stmt using @a;
set @a='2010-08-08';
execute stmt using @a;
execute stmt using @a;
+
+--echo #
+--echo # Bug #892725: look-up is changed for a full scan when executing PS
+--echo #
+
+create table t1 (a int primary key, b int);
+insert into t1 values
+ (7,70), (3,40), (4,40), (8,70), (1,70), (9,50), (2,70);
+
+prepare st from 'select * from t1 where a=8';
+
+flush status;
+execute st;
+show status like '%Handler_read%';
+flush status;
+execute st;
+show status like '%Handler_read%';
+flush status;
+select * from t1 use index() where a=3;
+show status like '%Handler_read%';
+flush status;
+execute st;
+show status like '%Handler_read%';
+
+deallocate prepare st;
+
+drop table t1;
+
diff --git a/mysql-test/t/range_vs_index_merge.test b/mysql-test/t/range_vs_index_merge.test
index 2ffa2d8eb49..de7e6a0838c 100755
--- a/mysql-test/t/range_vs_index_merge.test
+++ b/mysql-test/t/range_vs_index_merge.test
@@ -1030,9 +1030,8 @@ SELECT * FROM t1,t2,t3
DROP TABLE t1,t2,t3;
#
-# LP bug #823301: index merge union with prossible index scan
+# LP bug #823301: index merge sort union with possible index scan
#
-#
CREATE TABLE t1 (
a int, b int, c int, d int,
@@ -1058,5 +1057,38 @@ SET SESSION optimizer_switch=DEFAULT;
DROP TABLE t1;
+#
+# LP bug #800184: possible index merge sort union
+#
+
+CREATE TABLE t1 (a int NOT NULL PRIMARY KEY, b int, c int, INDEX idx(c,b));
+INSERT INTO t1 VALUES (19,1,NULL), (20,5,7);
+
+EXPLAIN
+SELECT * FROM t1
+ WHERE t1.a>300 AND t1.c!=0 AND t1.b>=350 AND t1.b<=400 AND
+ (t1.c=0 OR t1.a=500);
+SELECT * FROM t1
+ WHERE t1.a>300 AND t1.c!=0 AND t1.b>=350 AND t1.b<=400 AND
+ (t1.c=0 OR t1.a=500);
+
+DROP TABLE t1;
+
+#
+# LP bug #891953: always true OR
+#
+
+CREATE TABLE t1 (a int PRIMARY KEY, b int, INDEX idx(b));
+INSERT INTO t1 VALUES (167,9999), (168,10000);
+
+EXPLAIN
+SELECT * FROM t1
+ WHERE a BETWEEN 4 AND 5 AND b IN (255,4) OR a IN (2,14,25) OR a!=2;
+SELECT * FROM t1
+ WHERE a BETWEEN 4 AND 5 AND b IN (255,4) OR a IN (2,14,25) OR a!=2;
+
+DROP TABLE t1;
+
#the following command must be the last one in the file
set session optimizer_switch='index_merge_sort_intersection=default';
+
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 6369e4edbeb..3d7050ebc25 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -5063,4 +5063,14 @@ SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+--echo #
+--echo # LP BUG#833777 Performance regression with deeply nested subqueries
+--echo #
+
+create table t1 (a int not null, b char(10) not null);
+insert into t1 values (1, 'a');
+set @@optimizer_switch='in_to_exists=on,semijoin=off,materialization=off,subquery_cache=off';
+select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1 where a in (select a from t1)))))))))))))))))))))))))))));
+drop table t1;
+
set optimizer_switch=@subselect_tmp;
diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test
index 13c4b532c74..3800b019462 100644
--- a/mysql-test/t/subselect3.test
+++ b/mysql-test/t/subselect3.test
@@ -872,12 +872,17 @@ create table t12 select * from t1 where b = 67 AND (c IS NULL OR c > NOW()) orde
create table t21 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 asc;
create table t22 select * from t1 where b = 67 AND (c IS NULL OR c > '2005-12-08') order by 3 desc;
+set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch='materialization=off';
+
update t22 set c = '2005-12-08 15:58:27' where a = 255;
explain select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
select t21.* from t21,t22 where t21.a = t22.a and
t22.a in (select t12.a from t11, t12 where t11.a in(255,256) and t11.a = t12.a and t11.c is null) and t22.c is null order by t21.a;
+set @@optimizer_switch=@save_optimizer_switch;
+
drop table t1, t11, t12, t21, t22;
#
@@ -888,7 +893,7 @@ drop table t1, t11, t12, t21, t22;
create table t1(a int);
insert into t1 values (0),(1);
-set @@optimizer_switch='firstmatch=off';
+set @@optimizer_switch='firstmatch=off,materialization=off';
explain
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
select (select max(Y.a) from t1 Y where a in (select a from t1 Z) and a < X.a) as subq from t1 X;
@@ -914,6 +919,9 @@ select * from t1 where 2 in (select a from t0);
set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch='materialization=off';
+
#
# FirstMatch referring to a derived table
#
@@ -943,6 +951,8 @@ and t4.pk=t1.c);
drop table t1, t3, t4;
+set @@optimizer_switch=@save_optimizer_switch;
+
#
# Test if we handle duplicate elimination temptable overflowing to disk
#
@@ -997,6 +1007,9 @@ explain select * from t1 where a in (select a from t1);
drop table t1;
set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch=@save_optimizer_switch;
+set @@optimizer_switch='materialization=off';
+
#
# SJ-Materialization-scan for non-first table
#
@@ -1040,6 +1053,8 @@ explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
drop table t1,t2;
+set @@optimizer_switch=@save_optimizer_switch;
+
#
# Multi-column sj-materialization with lookups
#
@@ -1048,7 +1063,7 @@ insert into t1 select a,a from t0;
create table t2 (a int, b int);
insert into t2 select A.a + 10*B.a, A.a + 10*B.a from t0 A, t0 B;
-set @@optimizer_switch='firstmatch=off';
+set @@optimizer_switch='firstmatch=off,materialization=off';
explain select * from t1 where (a,b) in (select a,b from t2);
# A smallish test if find_best() still works for semi-join optimization:
@@ -1060,6 +1075,7 @@ set @@optimizer_switch=@save_optimizer_switch;
drop table t0, t1, t2;
+set @@optimizer_switch='materialization=off';
#
# Primitive SJ-Materialization tests for DECIMAL and DATE
@@ -1094,6 +1110,8 @@ explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y,
drop table t0,t1,t2;
+set @@optimizer_switch=@save_optimizer_switch;
+
--echo
--echo BUG#37842: Assertion in DsMrr_impl::dsmrr_init, at handler.cc:4307
--echo
@@ -1150,12 +1168,15 @@ create table t3 (
insert into t3 values (1,1, 'foo'), (2,2,'bar');
--echo The following must be converted to a semi-join:
+set @save_optimizer_switch=@@optimizer_switch;
+set @@optimizer_switch='materialization=off';
explain extended SELECT a.idIndividual FROM t1 a
WHERE a.idIndividual IN
( SELECT c.idObj FROM t3 cona
INNER JOIN t2 c ON c.idContact=cona.idContact
WHERE cona.postalStripped='T2H3B2'
);
+set @@optimizer_switch=@save_optimizer_switch;
drop table t1,t2,t3;
--echo #
diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test
index 41ca1762fef..a5a4e0a3cfe 100644
--- a/mysql-test/t/subselect4.test
+++ b/mysql-test/t/subselect4.test
@@ -126,6 +126,9 @@ INSERT INTO t4 VALUES (1), (2), (3);
CREATE TABLE t5 ( a INT );
INSERT INTO t5 VALUES (NULL), (2);
+SET @old_optimizer_switch = @@session.optimizer_switch;
+SET SESSION optimizer_switch = 'materialization=off,in_to_exists=on,semijoin=off';
+
--replace_column 1 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x
EXPLAIN
SELECT * FROM t1 WHERE ( a, b ) NOT IN ( SELECT c, d FROM t2 );
@@ -167,6 +170,8 @@ SELECT * FROM t1 WHERE b NOT IN ( SELECT c FROM t2 WHERE c = 1 );
SELECT * FROM t1 WHERE NULL NOT IN ( SELECT c FROM t2 WHERE c = 1 AND c <> 1 );
+SET SESSION optimizer_switch = @old_optimizer_switch;
+
DROP TABLE t1, t2, t3, t4, t5;
--echo #
diff --git a/mysql-test/t/subselect_mat_cost_bugs.test b/mysql-test/t/subselect_mat_cost_bugs.test
index 2e5dd71f9af..4ce19012e0c 100644
--- a/mysql-test/t/subselect_mat_cost_bugs.test
+++ b/mysql-test/t/subselect_mat_cost_bugs.test
@@ -323,7 +323,7 @@ create index key1 on t2 (kp1, kp2);
create index key2 on t2 (kp1);
create index key3 on t2 (kp2);
-set session optimizer_switch='default';
+SET @@optimizer_switch='materialization=off,semijoin=off,in_to_exists=on';
analyze table t2;
@@ -331,6 +331,8 @@ explain
select c1 from t1 where c1 in (select kp1 from t2 where kp2 = 10 and c2 = 4) or c1 > 7;
select c1 from t1 where c1 in (select kp1 from t2 where kp2 = 10 and c2 = 4) or c1 > 7;
+set @@optimizer_switch='default';
+
drop table t1, t2;
--echo #
diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test
index 740289ffcc8..5ae968742aa 100644
--- a/mysql-test/t/subselect_sj.test
+++ b/mysql-test/t/subselect_sj.test
@@ -1880,5 +1880,35 @@ set optimizer_switch= @tmp_otimizer_switch;
drop table t1,t2;
+--echo #
+--echo # Bug #887496: semijoin with IN equality for the second part of an index
+--echo #
+
+CREATE TABLE t1 (a int);
+INSERT INTO t1 VALUES (9), (0), (8), (5);
+
+CREATE TABLE t2 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t2 VALUES (5,'r'), (5,'z');
+
+CREATE TABLE t3 (a int, b varchar(1), INDEX idx (b,a));
+INSERT INTO t3 VALUES (5,'r'), (5,'z');
+
+set @tmp_otimizer_switch= @@optimizer_switch;
+SET SESSION optimizer_switch='semijoin=on,firstmatch=on';
+
+SET SESSION optimizer_switch='loosescan=off';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+
+SET SESSION optimizer_switch='loosescan=on';
+EXPLAIN
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+SELECT * FROM t1 WHERE a IN (SELECT t2.a FROM t2,t3 WHERE t2.b = t3.b);
+
+set optimizer_switch= @tmp_otimizer_switch;
+
+DROP TABLE t1,t2,t3;
+
# The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/t/subselect_sj_jcl6.test b/mysql-test/t/subselect_sj_jcl6.test
index e475adbf9a8..fc539ec1a01 100644
--- a/mysql-test/t/subselect_sj_jcl6.test
+++ b/mysql-test/t/subselect_sj_jcl6.test
@@ -43,6 +43,48 @@ SELECT * FROM t0 WHERE t0.a IN
set optimizer_switch=@save_optimizer_switch;
drop table t0, t1, t2;
+--echo #
+--echo # Bug #891995: IN subquery with join_cache_level >= 3
+--echo #
+
+CREATE TABLE t1 (a varchar(1));
+INSERT INTO t1 VALUES ('w'),('q');
+
+CREATE TABLE t2 (a int NOT NULL, b time, PRIMARY KEY (a));
+INSERT INTO t2 VALUES
+ (2,'18:56:33'), (5,'19:11:10'), (3,'18:56:33'), (7,'19:11:10');
+
+CREATE TABLE t3 (
+ a int NOT NULL, b int, c int, d varchar(1), PRIMARY KEY (a), KEY (d,c)
+);
+INSERT INTO t3 VALUES
+ (25,158,10,'f'), (26,5,2,'v'), (27,163,103,'f'), (28,2,3,'q'), (29,8,6,'y');
+
+set @save_optimizer_switch=@@optimizer_switch;
+SET SESSION optimizer_switch='semijoin=on';
+
+SET SESSION optimizer_switch='join_cache_hashed=on';
+SET SESSION join_cache_level=3;
+EXPLAIN
+SELECT * FROM t1, t2
+ WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
+SELECT * FROM t1, t2
+ WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
+
+
+SET SESSION optimizer_switch='mrr=on';
+SET SESSION join_cache_level=6;
+EXPLAIN
+SELECT * FROM t1, t2
+ WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
+SELECT * FROM t1, t2
+ WHERE t2.a IN (SELECT b FROM t3 WHERE t3.d <= t1.a);
+
+set optimizer_switch=@save_optimizer_switch;
+set join_cache_level=default;
+
+DROP TABLE t1,t2,t3;
+
--echo # End
set join_cache_level=default;
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 6d7b73ffcee..913b82bcb63 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -81,6 +81,7 @@ SET (SQL_SOURCE
create_options.cc multi_range_read.cc
opt_index_cond_pushdown.cc opt_subselect.cc
opt_table_elimination.cc sql_expression_cache.cc
+ gcalc_slicescan.cc gcalc_tools.cc
${GEN_SOURCES}
${MYSYS_LIBWRAP_SOURCE})
diff --git a/sql/field.cc b/sql/field.cc
index 42d71477372..480d36c2e28 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -7524,7 +7524,7 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
goto err;
// Check given WKB
uint32 wkb_type;
- if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2)
+ if (length < SRID_SIZE + WKB_HEADER_SIZE + 4)
goto err;
wkb_type= uint4korr(from + SRID_SIZE + 1);
if (wkb_type < (uint32) Geometry::wkb_point ||
diff --git a/sql/gcalc_slicescan.cc b/sql/gcalc_slicescan.cc
new file mode 100644
index 00000000000..cc2b26a8665
--- /dev/null
+++ b/sql/gcalc_slicescan.cc
@@ -0,0 +1,1966 @@
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+ Copyright (C) 2011 Monty Program Ab.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <m_string.h>
+
+#ifdef HAVE_SPATIAL
+
+#include "gcalc_slicescan.h"
+
+
+#define PH_DATA_OFFSET 8
+#define coord_to_float(d) ((double) d)
+#define coord_eq(a, b) (a == b)
+
+typedef int (*sc_compare_func)(const void*, const void*);
+
+#define LS_LIST_ITEM Gcalc_dyn_list::Item
+#define LS_COMPARE_FUNC_DECL sc_compare_func compare,
+#define LS_COMPARE_FUNC_CALL(list_el1, list_el2) (*compare)(list_el1, list_el2)
+#define LS_NEXT(A) (A)->next
+#define LS_SET_NEXT(A,val) (A)->next= val
+#define LS_P_NEXT(A) &(A)->next
+#define LS_NAME sort_list
+#define LS_SCOPE static
+#define LS_STRUCT_NAME sort_list_stack_struct
+#include "plistsort.c"
+
+
+#define GCALC_COORD_MINUS 0x80000000
+#define FIRST_DIGIT(d) ((d) & 0x7FFFFFFF)
+#define GCALC_SIGN(d) ((d) & 0x80000000)
+
+static Gcalc_scan_iterator::point *eq_sp(const Gcalc_heap::Info *pi)
+{
+ GCALC_DBUG_ASSERT(pi->type == Gcalc_heap::nt_eq_node);
+ return (Gcalc_scan_iterator::point *) pi->eq_data;
+}
+
+
+static Gcalc_scan_iterator::intersection_info *i_data(const Gcalc_heap::Info *pi)
+{
+ GCALC_DBUG_ASSERT(pi->type == Gcalc_heap::nt_intersection);
+ return (Gcalc_scan_iterator::intersection_info *) pi->intersection_data;
+}
+
+
+#ifndef GCALC_DBUG_OFF
+
+int gcalc_step_counter= 0;
+
+void GCALC_DBUG_CHECK_COUNTER()
+{
+ if (++gcalc_step_counter == 0)
+ GCALC_DBUG_PRINT(("step_counter_0"));
+ else
+ GCALC_DBUG_PRINT(("%d step_counter", gcalc_step_counter));
+}
+
+
+const char *gcalc_ev_name(int ev)
+{
+ switch (ev)
+ {
+ case scev_none:
+ return "n";
+ case scev_thread:
+ return "t";
+ case scev_two_threads:
+ return "tt";
+ case scev_end:
+ return "e";
+ case scev_two_ends:
+ return "ee";
+ case scev_intersection:
+ return "i";
+ case scev_point:
+ return "p";
+ case scev_single_point:
+ return "sp";
+ default:;
+ };
+ GCALC_DBUG_ASSERT(0);
+ return "unk";
+}
+
+
+static int gcalc_pi_str(char *str, const Gcalc_heap::Info *pi, const char *postfix)
+{
+ return sprintf(str, "%s %d %d | %s %d %d%s",
+ GCALC_SIGN(pi->ix[0]) ? "-":"", FIRST_DIGIT(pi->ix[0]),pi->ix[1],
+ GCALC_SIGN(pi->iy[0]) ? "-":"", FIRST_DIGIT(pi->iy[0]),pi->iy[1],
+ postfix);
+
+}
+
+
+static void GCALC_DBUG_PRINT_PI(const Gcalc_heap::Info *pi)
+{
+ char buf[128];
+ int n_buf;
+ if (pi->type == Gcalc_heap::nt_intersection)
+ {
+ const Gcalc_scan_iterator::intersection_info *ic= i_data(pi);
+
+ GCALC_DBUG_PRINT(("intersection point %d %d",
+ ic->edge_a->thread, ic->edge_b->thread));
+ return;
+ }
+ if (pi->type == Gcalc_heap::nt_eq_node)
+ {
+ const Gcalc_scan_iterator::point *e= eq_sp(pi);
+ GCALC_DBUG_PRINT(("eq point %d", e->thread));
+ return;
+ }
+ n_buf= gcalc_pi_str(buf, pi, "");
+ buf[n_buf]= 0;
+ GCALC_DBUG_PRINT(("%s", buf));
+}
+
+
+static void GCALC_DBUG_PRINT_SLICE(const char *header,
+ const Gcalc_scan_iterator::point *slice)
+{
+ int nbuf;
+ char buf[1024];
+ nbuf= strlen(header);
+ strcpy(buf, header);
+ for (; slice; slice= slice->get_next())
+ {
+ int lnbuf= nbuf;
+ lnbuf+= sprintf(buf + lnbuf, "%d\t", slice->thread);
+ lnbuf+= sprintf(buf + lnbuf, "%s\t", gcalc_ev_name(slice->event));
+
+ lnbuf+= gcalc_pi_str(buf + lnbuf, slice->pi, "\t");
+ if (slice->is_bottom())
+ lnbuf+= sprintf(buf+lnbuf, "bt\t");
+ else
+ lnbuf+= gcalc_pi_str(buf+lnbuf, slice->next_pi, "\t");
+ buf[lnbuf]= 0;
+ GCALC_DBUG_PRINT(("%s", buf));
+ }
+}
+
+
+#else
+#define GCALC_DBUG_CHECK_COUNTER() do { } while(0)
+#define GCALC_DBUG_PRINT_PI(pi) do { } while(0)
+#define GCALC_DBUG_PRINT_SLICE(a, b) do { } while(0)
+#define GCALC_DBUG_PRINT_INTERSECTIONS(a) do { } while(0)
+#define GCALC_DBUG_PRINT_STATE(a) do { } while(0)
+#endif /*GCALC_DBUG_OFF*/
+
+
+Gcalc_dyn_list::Gcalc_dyn_list(size_t blk_size, size_t sizeof_item):
+ m_blk_size(blk_size - ALLOC_ROOT_MIN_BLOCK_SIZE),
+ m_sizeof_item(ALIGN_SIZE(sizeof_item)),
+ m_points_per_blk((m_blk_size - PH_DATA_OFFSET) / m_sizeof_item),
+ m_blk_hook(&m_first_blk),
+ m_free(NULL),
+ m_keep(NULL)
+{}
+
+
+void Gcalc_dyn_list::format_blk(void* block)
+{
+ Item *pi_end, *cur_pi, *first_pi;
+ GCALC_DBUG_ASSERT(m_free == NULL);
+ first_pi= cur_pi= (Item *)(((char *)block) + PH_DATA_OFFSET);
+ pi_end= ptr_add(first_pi, m_points_per_blk - 1);
+ do {
+ cur_pi= cur_pi->next= ptr_add(cur_pi, 1);
+ } while (cur_pi<pi_end);
+ cur_pi->next= m_free;
+ m_free= first_pi;
+}
+
+
+Gcalc_dyn_list::Item *Gcalc_dyn_list::alloc_new_blk()
+{
+ void *new_block= my_malloc(m_blk_size, MYF(MY_WME));
+ if (!new_block)
+ return NULL;
+ *m_blk_hook= new_block;
+ m_blk_hook= (void**)new_block;
+ format_blk(new_block);
+ return new_item();
+}
+
+
+static void free_blk_list(void *list)
+{
+ void *next_blk;
+ while (list)
+ {
+ next_blk= *((void **)list);
+ my_free(list);
+ list= next_blk;
+ }
+}
+
+
+void Gcalc_dyn_list::cleanup()
+{
+ *m_blk_hook= NULL;
+ free_blk_list(m_first_blk);
+ m_first_blk= NULL;
+ m_blk_hook= &m_first_blk;
+ m_free= NULL;
+}
+
+
+Gcalc_dyn_list::~Gcalc_dyn_list()
+{
+ cleanup();
+}
+
+
+void Gcalc_dyn_list::reset()
+{
+ *m_blk_hook= NULL;
+ if (m_first_blk)
+ {
+ free_blk_list(*((void **)m_first_blk));
+ m_blk_hook= (void**)m_first_blk;
+ m_free= NULL;
+ format_blk(m_first_blk);
+ }
+}
+
+
+/* Internal coordinate operations implementations */
+
+void gcalc_set_zero(Gcalc_internal_coord *d, int d_len)
+{
+ do
+ {
+ d[--d_len]= 0;
+ } while (d_len);
+}
+
+
+int gcalc_is_zero(const Gcalc_internal_coord *d, int d_len)
+{
+ do
+ {
+ if (d[--d_len] != 0)
+ return 0;
+ } while (d_len);
+ return 1;
+}
+
+
+#ifdef GCALC_CHECK_WITH_FLOAT
+static double *gcalc_coord_extent= NULL;
+
+long double gcalc_get_double(const Gcalc_internal_coord *d, int d_len)
+{
+ int n= 1;
+ long double res= (long double) FIRST_DIGIT(d[0]);
+ do
+ {
+ res*= (long double) GCALC_DIG_BASE;
+ res+= (long double) d[n];
+ } while(++n < d_len);
+
+ n= 0;
+ do
+ {
+ if ((n & 1) && gcalc_coord_extent)
+ res/= *gcalc_coord_extent;
+ } while(++n < d_len);
+
+ if (GCALC_SIGN(d[0]))
+ res*= -1.0;
+ return res;
+}
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+
+
+static void do_add(Gcalc_internal_coord *result, int result_len,
+ const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b)
+{
+ int n_digit= result_len-1;
+ gcalc_digit_t carry= 0;
+
+ do
+ {
+ if ((result[n_digit]=
+ a[n_digit] + b[n_digit] + carry) >= GCALC_DIG_BASE)
+ {
+ carry= 1;
+ result[n_digit]-= GCALC_DIG_BASE;
+ }
+ else
+ carry= 0;
+ } while (--n_digit);
+
+ result[0]= (a[0] + FIRST_DIGIT(b[0]) + carry);
+
+ GCALC_DBUG_ASSERT(FIRST_DIGIT(result[0]) < GCALC_DIG_BASE);
+}
+
+
+static void do_sub(Gcalc_internal_coord *result, int result_len,
+ const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b)
+{
+ int n_digit= result_len-1;
+ gcalc_digit_t carry= 0;
+ gcalc_digit_t cur_b, cur_a;
+
+ do
+ {
+ cur_b= b[n_digit] + carry;
+ cur_a= a[n_digit];
+ if (cur_a < cur_b)
+ {
+ carry= 1;
+ result[n_digit]= (GCALC_DIG_BASE - cur_b) + cur_a;
+ }
+ else
+ {
+ carry= 0;
+ result[n_digit]= cur_a - cur_b;
+ }
+ } while (--n_digit);
+
+
+ result[0]= a[0] - FIRST_DIGIT(b[0]) - carry;
+
+ GCALC_DBUG_ASSERT(FIRST_DIGIT(a[0]) >= FIRST_DIGIT(b[0]) + carry);
+ GCALC_DBUG_ASSERT(!gcalc_is_zero(result, result_len));
+}
+/*
+static void do_sub(Gcalc_internal_coord *result, int result_len,
+ const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b)
+{
+ int n_digit= result_len-1;
+ gcalc_digit_t carry= 0;
+
+ do
+ {
+ if ((result[n_digit]= a[n_digit] - b[n_digit] - carry) < 0)
+ {
+ carry= 1;
+ result[n_digit]+= GCALC_DIG_BASE;
+ }
+ else
+ carry= 0;
+ } while (--n_digit);
+
+
+ result[0]= a[0] - FIRST_DIGIT(b[0]) - carry;
+
+ GCALC_DBUG_ASSERT(FIRST_DIGIT(a[0]) - FIRST_DIGIT(b[0]) - carry >= 0);
+ GCALC_DBUG_ASSERT(!gcalc_is_zero(result, result_len));
+}
+*/
+
+static int do_cmp(const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b, int len)
+{
+ int n_digit= 1;
+
+ if ((FIRST_DIGIT(a[0]) != FIRST_DIGIT(b[0])))
+ return FIRST_DIGIT(a[0]) > FIRST_DIGIT(b[0]) ? 1 : -1;
+
+ do
+ {
+ if ((a[n_digit] != b[n_digit]))
+ return a[n_digit] > b[n_digit] ? 1 : -1;
+ } while (++n_digit < len);
+
+ return 0;
+}
+
+
+#ifdef GCALC_CHECK_WITH_FLOAT
+static int de_weak_check(long double a, long double b, long double ex)
+{
+ long double d= a - b;
+ if (d < ex && d > -ex)
+ return 1;
+
+ d/= fabsl(a) + fabsl(b);
+ if (d < ex && d > -ex)
+ return 1;
+ return 0;
+}
+
+static int de_check(long double a, long double b)
+{
+ return de_weak_check(a, b, (long double) 1e-10);
+}
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+
+
+void gcalc_mul_coord(Gcalc_internal_coord *result, int result_len,
+ const Gcalc_internal_coord *a, int a_len,
+ const Gcalc_internal_coord *b, int b_len)
+{
+ GCALC_DBUG_ASSERT(result_len == a_len + b_len);
+ GCALC_DBUG_ASSERT(a_len >= b_len);
+ int n_a, n_b, n_res;
+ gcalc_digit_t carry= 0;
+
+ gcalc_set_zero(result, result_len);
+
+ n_a= a_len - 1;
+ do
+ {
+ gcalc_coord2 cur_a= n_a ? a[n_a] : FIRST_DIGIT(a[0]);
+ n_b= b_len - 1;
+ do
+ {
+ gcalc_coord2 cur_b= n_b ? b[n_b] : FIRST_DIGIT(b[0]);
+ gcalc_coord2 mul= cur_a * cur_b + carry + result[n_a + n_b + 1];
+ result[n_a + n_b + 1]= mul % GCALC_DIG_BASE;
+ carry= (gcalc_digit_t) (mul / GCALC_DIG_BASE);
+ } while (n_b--);
+ if (carry)
+ {
+ for (n_res= n_a; (result[n_res]+= carry) >= GCALC_DIG_BASE;
+ n_res--)
+ {
+ result[n_res]-= GCALC_DIG_BASE;
+ carry= 1;
+ }
+ carry= 0;
+ }
+ } while (n_a--);
+ if (!gcalc_is_zero(result, result_len))
+ result[0]|= GCALC_SIGN(a[0] ^ b[0]);
+#ifdef GCALC_CHECK_WITH_FLOAT
+ GCALC_DBUG_ASSERT(de_check(gcalc_get_double(a, a_len) *
+ gcalc_get_double(b, b_len),
+ gcalc_get_double(result, result_len)));
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+}
+
+
+inline void gcalc_mul_coord1(Gcalc_coord1 result,
+ const Gcalc_coord1 a, const Gcalc_coord1 b)
+{
+ return gcalc_mul_coord(result, GCALC_COORD_BASE2,
+ a, GCALC_COORD_BASE, b, GCALC_COORD_BASE);
+}
+
+
+void gcalc_add_coord(Gcalc_internal_coord *result, int result_len,
+ const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b)
+{
+ if (GCALC_SIGN(a[0]) == GCALC_SIGN(b[0]))
+ do_add(result, result_len, a, b);
+ else
+ {
+ int cmp_res= do_cmp(a, b, result_len);
+ if (cmp_res == 0)
+ gcalc_set_zero(result, result_len);
+ else if (cmp_res > 0)
+ do_sub(result, result_len, a, b);
+ else
+ do_sub(result, result_len, b, a);
+ }
+#ifdef GCALC_CHECK_WITH_FLOAT
+ GCALC_DBUG_ASSERT(de_check(gcalc_get_double(a, result_len) +
+ gcalc_get_double(b, result_len),
+ gcalc_get_double(result, result_len)));
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+}
+
+
+void gcalc_sub_coord(Gcalc_internal_coord *result, int result_len,
+ const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b)
+{
+ if (GCALC_SIGN(a[0] ^ b[0]))
+ do_add(result, result_len, a, b);
+ else
+ {
+ int cmp_res= do_cmp(a, b, result_len);
+ if (cmp_res == 0)
+ gcalc_set_zero(result, result_len);
+ else if (cmp_res > 0)
+ do_sub(result, result_len, a, b);
+ else
+ {
+ do_sub(result, result_len, b, a);
+ result[0]^= GCALC_COORD_MINUS;
+ }
+ }
+#ifdef GCALC_CHECK_WITH_FLOAT
+ GCALC_DBUG_ASSERT(de_check(gcalc_get_double(a, result_len) -
+ gcalc_get_double(b, result_len),
+ gcalc_get_double(result, result_len)));
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+}
+
+
+inline void gcalc_sub_coord1(Gcalc_coord1 result,
+ const Gcalc_coord1 a, const Gcalc_coord1 b)
+{
+ return gcalc_sub_coord(result, GCALC_COORD_BASE, a, b);
+}
+
+
+int gcalc_cmp_coord(const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b, int len)
+{
+ int n_digit= 0;
+ int result= 0;
+
+ do
+ {
+ if (a[n_digit] == b[n_digit])
+ {
+ n_digit++;
+ continue;
+ }
+ if (a[n_digit] > b[n_digit])
+ result= GCALC_SIGN(a[0]) ? -1 : 1;
+ else
+ result= GCALC_SIGN(b[0]) ? 1 : -1;
+ break;
+
+ } while (n_digit < len);
+
+#ifdef GCALC_CHECK_WITH_FLOAT
+ if (result == 0)
+ GCALC_DBUG_ASSERT(de_check(gcalc_get_double(a, len),
+ gcalc_get_double(b, len)));
+ else if (result == 1)
+ GCALC_DBUG_ASSERT(de_check(gcalc_get_double(a, len),
+ gcalc_get_double(b, len)) ||
+ gcalc_get_double(a, len) > gcalc_get_double(b, len));
+ else
+ GCALC_DBUG_ASSERT(de_check(gcalc_get_double(a, len),
+ gcalc_get_double(b, len)) ||
+ gcalc_get_double(a, len) < gcalc_get_double(b, len));
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+ return result;
+}
+
+
+#define gcalc_cmp_coord1(a, b) gcalc_cmp_coord(a, b, GCALC_COORD_BASE)
+
+int gcalc_set_double(Gcalc_internal_coord *c, double d, double ext)
+{
+ int sign;
+ double ds= d * ext;
+ if ((sign= ds < 0))
+ ds= -ds;
+ c[0]= (gcalc_digit_t) (ds / (double) GCALC_DIG_BASE);
+ c[1]= (gcalc_digit_t) (ds - ((double) c[0]) * (double) GCALC_DIG_BASE);
+ if (c[1] >= GCALC_DIG_BASE)
+ {
+ c[1]= 0;
+ c[0]++;
+ }
+ if (sign)
+ c[0]|= GCALC_COORD_MINUS;
+#ifdef GCALC_CHECK_WITH_FLOAT
+ GCALC_DBUG_ASSERT(de_check(d, gcalc_get_double(c, 2)));
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+ return 0;
+}
+
+
+typedef gcalc_digit_t Gcalc_coord4[GCALC_COORD_BASE*4];
+typedef gcalc_digit_t Gcalc_coord5[GCALC_COORD_BASE*5];
+
+
+void Gcalc_scan_iterator::intersection_info::do_calc_t()
+{
+ Gcalc_coord1 a2_a1x, a2_a1y;
+ Gcalc_coord2 x1y2, x2y1;
+
+ gcalc_sub_coord1(a2_a1x, edge_b->pi->ix, edge_a->pi->ix);
+ gcalc_sub_coord1(a2_a1y, edge_b->pi->iy, edge_a->pi->iy);
+
+ GCALC_DBUG_ASSERT(!gcalc_is_zero(edge_a->dy, GCALC_COORD_BASE) ||
+ !gcalc_is_zero(edge_b->dy, GCALC_COORD_BASE));
+
+ gcalc_mul_coord1(x1y2, edge_a->dx, edge_b->dy);
+ gcalc_mul_coord1(x2y1, edge_a->dy, edge_b->dx);
+ gcalc_sub_coord(t_b, GCALC_COORD_BASE2, x1y2, x2y1);
+
+
+ gcalc_mul_coord1(x1y2, a2_a1x, edge_b->dy);
+ gcalc_mul_coord1(x2y1, a2_a1y, edge_b->dx);
+ gcalc_sub_coord(t_a, GCALC_COORD_BASE2, x1y2, x2y1);
+ t_calculated= 1;
+}
+
+
+void Gcalc_scan_iterator::intersection_info::do_calc_y()
+{
+ GCALC_DBUG_ASSERT(t_calculated);
+
+ Gcalc_coord3 a_tb, b_ta;
+
+ gcalc_mul_coord(a_tb, GCALC_COORD_BASE3,
+ t_b, GCALC_COORD_BASE2, edge_a->pi->iy, GCALC_COORD_BASE);
+ gcalc_mul_coord(b_ta, GCALC_COORD_BASE3,
+ t_a, GCALC_COORD_BASE2, edge_a->dy, GCALC_COORD_BASE);
+
+ gcalc_add_coord(y_exp, GCALC_COORD_BASE3, a_tb, b_ta);
+ y_calculated= 1;
+}
+
+
+void Gcalc_scan_iterator::intersection_info::do_calc_x()
+{
+ GCALC_DBUG_ASSERT(t_calculated);
+
+ Gcalc_coord3 a_tb, b_ta;
+
+ gcalc_mul_coord(a_tb, GCALC_COORD_BASE3,
+ t_b, GCALC_COORD_BASE2, edge_a->pi->ix, GCALC_COORD_BASE);
+ gcalc_mul_coord(b_ta, GCALC_COORD_BASE3,
+ t_a, GCALC_COORD_BASE2, edge_a->dx, GCALC_COORD_BASE);
+
+ gcalc_add_coord(x_exp, GCALC_COORD_BASE3, a_tb, b_ta);
+ x_calculated= 1;
+}
+
+
+static int cmp_node_isc(const Gcalc_heap::Info *node,
+ const Gcalc_heap::Info *isc)
+{
+ GCALC_DBUG_ASSERT(node->type == Gcalc_heap::nt_shape_node);
+ Gcalc_scan_iterator::intersection_info *inf= i_data(isc);
+ Gcalc_coord3 exp;
+ int result;
+
+ inf->calc_t();
+ inf->calc_y_exp();
+
+ gcalc_mul_coord(exp, GCALC_COORD_BASE3,
+ inf->t_b, GCALC_COORD_BASE2, node->iy, GCALC_COORD_BASE);
+
+ result= gcalc_cmp_coord(exp, inf->y_exp, GCALC_COORD_BASE3);
+#ifdef GCALC_CHECK_WITH_FLOAT
+ long double int_x, int_y;
+ isc->calc_xy_ld(&int_x, &int_y);
+ if (result < 0)
+ {
+ if (!de_check(int_y, node->y) && node->y > int_y)
+ GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g < %LG", node->y, int_y));
+ }
+ else if (result > 0)
+ {
+ if (!de_check(int_y, node->y) && node->y < int_y)
+ GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g > %LG", node->y, int_y));
+ }
+ else
+ {
+ if (!de_check(int_y, node->y))
+ GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g == %LG", node->y, int_y));
+ }
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+ if (result)
+ goto exit;
+
+
+ inf->calc_x_exp();
+ gcalc_mul_coord(exp, GCALC_COORD_BASE3,
+ inf->t_b, GCALC_COORD_BASE2, node->ix, GCALC_COORD_BASE);
+
+ result= gcalc_cmp_coord(exp, inf->x_exp, GCALC_COORD_BASE3);
+#ifdef GCALC_CHECK_WITH_FLOAT
+ if (result < 0)
+ {
+ if (!de_check(int_x, node->x) && node->x > int_x)
+ GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g < %LG",
+ node->x, int_x));
+ }
+ else if (result > 0)
+ {
+ if (!de_check(int_x, node->x) && node->x < int_x)
+ GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g > %LG",
+ node->x, int_x));
+ }
+ else
+ {
+ if (!de_check(int_x, node->x))
+ GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g == %LG",
+ node->x, int_x));
+ }
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+exit:
+ return result;
+}
+
+
+static int cmp_intersections(const Gcalc_heap::Info *i1,
+ const Gcalc_heap::Info *i2)
+{
+ Gcalc_scan_iterator::intersection_info *inf1= i_data(i1);
+ Gcalc_scan_iterator::intersection_info *inf2= i_data(i2);
+ Gcalc_coord5 exp_a, exp_b;
+ int result;
+
+ inf1->calc_t();
+ inf2->calc_t();
+
+ inf1->calc_y_exp();
+ inf2->calc_y_exp();
+
+ gcalc_mul_coord(exp_a, GCALC_COORD_BASE5,
+ inf1->y_exp, GCALC_COORD_BASE3, inf2->t_b, GCALC_COORD_BASE2);
+ gcalc_mul_coord(exp_b, GCALC_COORD_BASE5,
+ inf2->y_exp, GCALC_COORD_BASE3, inf1->t_b, GCALC_COORD_BASE2);
+
+ result= gcalc_cmp_coord(exp_a, exp_b, GCALC_COORD_BASE5);
+#ifdef GCALC_CHECK_WITH_FLOAT
+ long double x1, y1, x2, y2;
+ i1->calc_xy_ld(&x1, &y1);
+ i2->calc_xy_ld(&x2, &y2);
+
+ if (result < 0)
+ {
+ if (!de_check(y1, y2) && y2 > y1)
+ GCALC_DBUG_PRINT(("floatcheck cmp_intersections_y failed %LG < %LG",
+ y2, y1));
+ }
+ else if (result > 0)
+ {
+ if (!de_check(y1, y2) && y2 < y1)
+ GCALC_DBUG_PRINT(("floatcheck cmp_intersections_y failed %LG > %LG",
+ y2, y1));
+ }
+ else
+ {
+ if (!de_check(y1, y2))
+ GCALC_DBUG_PRINT(("floatcheck cmp_intersections_y failed %LG == %LG",
+ y2, y1));
+ }
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+
+ if (result != 0)
+ return result;
+
+
+ inf1->calc_x_exp();
+ inf2->calc_x_exp();
+ gcalc_mul_coord(exp_a, GCALC_COORD_BASE5,
+ inf1->x_exp, GCALC_COORD_BASE3, inf2->t_b, GCALC_COORD_BASE2);
+ gcalc_mul_coord(exp_b, GCALC_COORD_BASE5,
+ inf2->x_exp, GCALC_COORD_BASE3, inf1->t_b, GCALC_COORD_BASE2);
+
+ result= gcalc_cmp_coord(exp_a, exp_b, GCALC_COORD_BASE5);
+#ifdef GCALC_CHECK_WITH_FLOAT
+ if (result < 0)
+ {
+ if (!de_check(x1, x2) && x2 > x1)
+ GCALC_DBUG_PRINT(("floatcheck cmp_intersectionsx failed %LG < %LG",
+ x2, x1));
+ }
+ else if (result > 0)
+ {
+ if (!de_check(x1, x2) && x2 < x1)
+ GCALC_DBUG_PRINT(("floatcheck cmp_intersectionsx failed %LG > %LG",
+ x2, x1));
+ }
+ else
+ {
+ if (!de_check(x1, x2))
+ GCALC_DBUG_PRINT(("floatcheck cmp_intersectionsx failed %LG == %LG",
+ x2, x1));
+ }
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+ return result;
+}
+/* Internal coordinates implementation end */
+
+
+Gcalc_heap::Info *Gcalc_heap::new_point_info(double x, double y,
+ gcalc_shape_info shape)
+{
+ double abs= fabs(x);
+ Info *result= (Info *)new_item();
+ if (!result)
+ return NULL;
+ *m_hook= result;
+ m_hook= &result->next;
+ result->x= x;
+ result->y= y;
+ result->shape= shape;
+ result->top_node= 1;
+ result->type= nt_shape_node;
+ if (m_n_points)
+ {
+ if (abs > coord_extent)
+ coord_extent= abs;
+ }
+ else
+ coord_extent= abs;
+
+ abs= fabs(y);
+ if (abs > coord_extent)
+ coord_extent= abs;
+
+ m_n_points++;
+ return result;
+}
+
+
+static Gcalc_heap::Info *new_intersection(
+ Gcalc_heap *heap, Gcalc_scan_iterator::intersection_info *ii)
+{
+ Gcalc_heap::Info *isc= (Gcalc_heap::Info *)heap->new_item();
+ if (!isc)
+ return 0;
+ isc->type= Gcalc_heap::nt_intersection;
+ isc->p1= ii->edge_a->pi;
+ isc->p2= ii->edge_a->next_pi;
+ isc->p3= ii->edge_b->pi;
+ isc->p4= ii->edge_b->next_pi;
+ isc->intersection_data= ii;
+ return isc;
+}
+
+
+static Gcalc_heap::Info *new_eq_point(
+ Gcalc_heap *heap, const Gcalc_heap::Info *p,
+ Gcalc_scan_iterator::point *edge)
+{
+ Gcalc_heap::Info *eqp= (Gcalc_heap::Info *)heap->new_item();
+ if (!eqp)
+ return 0;
+ eqp->type= Gcalc_heap::nt_eq_node;
+ eqp->node= p;
+ eqp->eq_data= edge;
+ return eqp;
+}
+
+
+void Gcalc_heap::Info::calc_xy(double *x, double *y) const
+{
+ double b0_x= p2->x - p1->x;
+ double b0_y= p2->y - p1->y;
+ double b1_x= p4->x - p3->x;
+ double b1_y= p4->y - p3->y;
+ double b0xb1= b0_x * b1_y - b0_y * b1_x;
+ double t= (p3->x - p1->x) * b1_y - (p3->y - p1->y) * b1_x;
+
+ t/= b0xb1;
+
+ *x= p1->x + b0_x * t;
+ *y= p1->y + b0_y * t;
+}
+
+
+#ifdef GCALC_CHECK_WITH_FLOAT
+void Gcalc_heap::Info::calc_xy_ld(long double *x, long double *y) const
+{
+ long double b0_x= ((long double) p2->x) - p1->x;
+ long double b0_y= ((long double) p2->y) - p1->y;
+ long double b1_x= ((long double) p4->x) - p3->x;
+ long double b1_y= ((long double) p4->y) - p3->y;
+ long double b0xb1= b0_x * b1_y - b0_y * b1_x;
+ long double ax= ((long double) p3->x) - p1->x;
+ long double ay= ((long double) p3->y) - p1->y;
+ long double t_a= ax * b1_y - ay * b1_x;
+ long double hx= (b0xb1 * (long double) p1->x + b0_x * t_a);
+ long double hy= (b0xb1 * (long double) p1->y + b0_y * t_a);
+
+ if (fabs(b0xb1) < 1e-15)
+ {
+ *x= p1->x;
+ *y= p1->y;
+ return;
+ }
+
+ *x= hx/b0xb1;
+ *y= hy/b0xb1;
+}
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+
+
+static int cmp_point_info(const Gcalc_heap::Info *i0,
+ const Gcalc_heap::Info *i1)
+{
+ int cmp_y= gcalc_cmp_coord1(i0->iy, i1->iy);
+ if (cmp_y)
+ return cmp_y;
+ return gcalc_cmp_coord1(i0->ix, i1->ix);
+}
+
+
+static inline void trim_node(Gcalc_heap::Info *node, Gcalc_heap::Info *prev_node)
+{
+ if (!node)
+ return;
+ node->top_node= 0;
+ GCALC_DBUG_ASSERT((node->left == prev_node) || (node->right == prev_node));
+ if (node->left == prev_node)
+ node->left= node->right;
+ node->right= NULL;
+ GCALC_DBUG_ASSERT(cmp_point_info(node, prev_node));
+}
+
+
+static int compare_point_info(const void *e0, const void *e1)
+{
+ const Gcalc_heap::Info *i0= (const Gcalc_heap::Info *)e0;
+ const Gcalc_heap::Info *i1= (const Gcalc_heap::Info *)e1;
+ return cmp_point_info(i0, i1) > 0;
+}
+
+
+#define GCALC_SCALE_1 1e18
+
+static double find_scale(double extent)
+{
+ double scale= 1e-2;
+ while (scale < extent)
+ scale*= (double ) 10;
+ return GCALC_SCALE_1 / scale / 10;
+}
+
+
+void Gcalc_heap::prepare_operation()
+{
+ Info *cur;
+ GCALC_DBUG_ASSERT(m_hook);
+ coord_extent= find_scale(coord_extent);
+#ifdef GCALC_CHECK_WITH_FLOAT
+ gcalc_coord_extent= &coord_extent;
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+ *m_hook= NULL;
+ m_hook= NULL; /* just to check it's not called twice */
+ for (cur= get_first(); cur; cur= cur->get_next())
+ {
+ gcalc_set_double(cur->ix, cur->x, coord_extent);
+ gcalc_set_double(cur->iy, cur->y, coord_extent);
+ }
+ m_first= sort_list(compare_point_info, m_first, m_n_points);
+
+ /* TODO - move this to the 'normal_scan' loop */
+ for (cur= get_first(); cur; cur= cur->get_next())
+ {
+ trim_node(cur->left, cur);
+ trim_node(cur->right, cur);
+ }
+}
+
+
+void Gcalc_heap::reset()
+{
+ if (m_n_points)
+ {
+ free_list(m_first);
+ m_n_points= 0;
+ }
+ m_hook= &m_first;
+}
+
+
+int Gcalc_shape_transporter::int_single_point(gcalc_shape_info Info,
+ double x, double y)
+{
+ Gcalc_heap::Info *point= m_heap->new_point_info(x, y, Info);
+ if (!point)
+ return 1;
+ point->left= point->right= 0;
+ return 0;
+}
+
+
+int Gcalc_shape_transporter::int_add_point(gcalc_shape_info Info,
+ double x, double y)
+{
+ Gcalc_heap::Info *point;
+ GCALC_DBUG_ASSERT(!m_prev || m_prev->x != x || m_prev->y != y);
+
+ if (!(point= m_heap->new_point_info(x, y, Info)))
+ return 1;
+ if (m_first)
+ {
+ m_prev->left= point;
+ point->right= m_prev;
+ }
+ else
+ m_first= point;
+ m_prev= point;
+ return 0;
+}
+
+
+void Gcalc_shape_transporter::int_complete()
+{
+ GCALC_DBUG_ASSERT(m_shape_started == 1 || m_shape_started == 3);
+
+ if (!m_first)
+ return;
+
+ /* simple point */
+ if (m_first == m_prev)
+ {
+ m_first->right= m_first->left= NULL;
+ return;
+ }
+
+ /* line */
+ if (m_shape_started == 1)
+ {
+ m_first->right= NULL;
+ m_prev->left= m_prev->right;
+ m_prev->right= NULL;
+ return;
+ }
+
+ GCALC_DBUG_ASSERT(m_prev->x != m_first->x || m_prev->y != m_first->y);
+ /* polygon */
+ m_first->right= m_prev;
+ m_prev->left= m_first;
+}
+
+
+inline void calc_dx_dy(Gcalc_scan_iterator::point *p)
+{
+ gcalc_sub_coord1(p->dx, p->next_pi->ix, p->pi->ix);
+ gcalc_sub_coord1(p->dy, p->next_pi->iy, p->pi->iy);
+ if (GCALC_SIGN(p->dx[0]))
+ {
+ p->l_border= &p->next_pi->ix;
+ p->r_border= &p->pi->ix;
+ }
+ else
+ {
+ p->r_border= &p->next_pi->ix;
+ p->l_border= &p->pi->ix;
+ }
+}
+
+
+Gcalc_scan_iterator::Gcalc_scan_iterator(size_t blk_size) :
+ Gcalc_dyn_list(blk_size, sizeof(point) > sizeof(intersection_info) ?
+ sizeof(point) :
+ sizeof(intersection_info))
+{
+ state.slice= NULL;
+ m_bottom_points= NULL;
+ m_bottom_hook= &m_bottom_points;
+}
+
+
+void Gcalc_scan_iterator::init(Gcalc_heap *points)
+{
+ GCALC_DBUG_ASSERT(points->ready());
+ GCALC_DBUG_ASSERT(!state.slice);
+
+ if (!(m_cur_pi= points->get_first()))
+ return;
+ m_heap= points;
+ state.event_position_hook= &state.slice;
+ state.event_end= NULL;
+#ifndef GCALC_DBUG_OFF
+ m_cur_thread= 0;
+#endif /*GCALC_DBUG_OFF*/
+ GCALC_SET_TERMINATED(killed, 0);
+}
+
+void Gcalc_scan_iterator::reset()
+{
+ state.slice= NULL;
+ m_bottom_points= NULL;
+ m_bottom_hook= &m_bottom_points;
+ Gcalc_dyn_list::reset();
+}
+
+
+int Gcalc_scan_iterator::point::cmp_dx_dy(const Gcalc_coord1 dx_a,
+ const Gcalc_coord1 dy_a,
+ const Gcalc_coord1 dx_b,
+ const Gcalc_coord1 dy_b)
+{
+ Gcalc_coord2 dx_a_dy_b;
+ Gcalc_coord2 dy_a_dx_b;
+ gcalc_mul_coord1(dx_a_dy_b, dx_a, dy_b);
+ gcalc_mul_coord1(dy_a_dx_b, dy_a, dx_b);
+
+ return gcalc_cmp_coord(dx_a_dy_b, dy_a_dx_b, GCALC_COORD_BASE2);
+}
+
+
+int Gcalc_scan_iterator::point::cmp_dx_dy(const Gcalc_heap::Info *p1,
+ const Gcalc_heap::Info *p2,
+ const Gcalc_heap::Info *p3,
+ const Gcalc_heap::Info *p4)
+{
+ Gcalc_coord1 dx_a, dy_a, dx_b, dy_b;
+ gcalc_sub_coord1(dx_a, p2->ix, p1->ix);
+ gcalc_sub_coord1(dy_a, p2->iy, p1->iy);
+ gcalc_sub_coord1(dx_b, p4->ix, p3->ix);
+ gcalc_sub_coord1(dy_b, p4->iy, p3->iy);
+ return cmp_dx_dy(dx_a, dy_a, dx_b, dy_b);
+}
+
+
+int Gcalc_scan_iterator::point::cmp_dx_dy(const point *p) const
+{
+ GCALC_DBUG_ASSERT(!is_bottom());
+ return cmp_dx_dy(dx, dy, p->dx, p->dy);
+}
+
+
+#ifdef GCALC_CHECK_WITH_FLOAT
+void Gcalc_scan_iterator::point::calc_x(long double *x, long double y,
+ long double ix) const
+{
+ long double ddy= gcalc_get_double(dy, GCALC_COORD_BASE);
+ if (fabsl(ddy) < (long double) 1e-20)
+ {
+ *x= ix;
+ }
+ else
+ *x= (ddy * (long double) pi->x + gcalc_get_double(dx, GCALC_COORD_BASE) *
+ (y - pi->y)) / ddy;
+}
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+
+
+static int compare_events(const void *e0, const void *e1)
+{
+ const Gcalc_scan_iterator::point *p0= (const Gcalc_scan_iterator::point *)e0;
+ const Gcalc_scan_iterator::point *p1= (const Gcalc_scan_iterator::point *)e1;
+ return p0->cmp_dx_dy(p1) > 0;
+}
+
+
+int Gcalc_scan_iterator::arrange_event(int do_sorting, int n_intersections)
+{
+ int ev_counter;
+ point *sp;
+ point **sp_hook;
+
+ ev_counter= 0;
+
+ *m_bottom_hook= NULL;
+ for (sp= m_bottom_points; sp; sp= sp->get_next())
+ sp->ev_next= sp->get_next();
+
+ for (sp= state.slice, sp_hook= &state.slice;
+ sp; sp_hook= sp->next_ptr(), sp= sp->get_next())
+ {
+ if (sp->event)
+ {
+ state.event_position_hook= sp_hook;
+ break;
+ }
+ }
+
+ for (sp= *(sp_hook= state.event_position_hook);
+ sp && sp->event; sp_hook= sp->next_ptr(), sp= sp->get_next())
+ {
+ ev_counter++;
+ if (sp->get_next() && sp->get_next()->event)
+ sp->ev_next= sp->get_next();
+ else
+ sp->ev_next= m_bottom_points;
+ }
+
+#ifndef GCALC_DBUG_OFF
+ {
+ point *cur_p= sp;
+ for (; cur_p; cur_p= cur_p->get_next())
+ GCALC_DBUG_ASSERT(!cur_p->event);
+ }
+#endif /*GCALC_DBUG_OFF*/
+
+ state.event_end= sp;
+
+ if (ev_counter == 2 && n_intersections == 1)
+ {
+ /* If we had only intersection, just swap the two points. */
+ sp= *state.event_position_hook;
+ *state.event_position_hook= sp->get_next();
+ sp->next= (*state.event_position_hook)->next;
+ (*state.event_position_hook)->next= sp;
+
+ /* The list of the events should be restored. */
+ (*state.event_position_hook)->ev_next= sp;
+ sp->ev_next= m_bottom_points;
+ }
+ else if (ev_counter == 2 && get_events()->event == scev_two_threads)
+ {
+ /* Do nothing. */
+ }
+ else if (ev_counter > 1 && do_sorting)
+ {
+ point *cur_p;
+ *sp_hook= NULL;
+ sp= (point *) sort_list(compare_events, *state.event_position_hook,
+ ev_counter);
+ /* Find last item in the list, it's changed after the sorting. */
+ for (cur_p= sp->get_next(); cur_p->get_next();
+ cur_p= cur_p->get_next())
+ {}
+ cur_p->next= state.event_end;
+ *state.event_position_hook= sp;
+ /* The list of the events should be restored. */
+ for (; sp && sp->event; sp= sp->get_next())
+ {
+ if (sp->get_next() && sp->get_next()->event)
+ sp->ev_next= sp->get_next();
+ else
+ sp->ev_next= m_bottom_points;
+ }
+ }
+
+#ifndef GCALC_DBUG_OFF
+ {
+ const event_point *ev= get_events();
+ for (; ev && ev->get_next(); ev= ev->get_next())
+ {
+ if (ev->is_bottom() || ev->get_next()->is_bottom())
+ break;
+ GCALC_DBUG_ASSERT(ev->cmp_dx_dy(ev->get_next()) <= 0);
+ }
+ }
+#endif /*GCALC_DBUG_OFF*/
+ return 0;
+}
+
+
+int Gcalc_heap::Info::equal_pi(const Info *pi) const
+{
+ if (type == nt_intersection)
+ return equal_intersection;
+ if (pi->type == nt_eq_node)
+ return 1;
+ if (type == nt_eq_node || pi->type == nt_intersection)
+ return 0;
+ return cmp_point_info(this, pi) == 0;
+}
+
+int Gcalc_scan_iterator::step()
+{
+ int result= 0;
+ int do_sorting= 0;
+ int n_intersections= 0;
+ point *sp;
+ GCALC_DBUG_ENTER("Gcalc_scan_iterator::step");
+ GCALC_DBUG_ASSERT(more_points());
+
+ if (GCALC_TERMINATED(killed))
+ GCALC_DBUG_RETURN(0xFFFF);
+
+ /* Clear the old event marks. */
+ if (m_bottom_points)
+ {
+ free_list((Gcalc_dyn_list::Item **) &m_bottom_points,
+ (Gcalc_dyn_list::Item **) m_bottom_hook);
+ m_bottom_points= NULL;
+ m_bottom_hook= &m_bottom_points;
+ }
+ for (sp= *state.event_position_hook;
+ sp != state.event_end; sp= sp->get_next())
+ sp->event= scev_none;
+
+//#ifndef GCALC_DBUG_OFF
+ state.event_position_hook= NULL;
+ state.pi= NULL;
+//#endif /*GCALC_DBUG_OFF*/
+
+ do
+ {
+#ifndef GCALC_DBUG_OFF
+ if (m_cur_pi->type == Gcalc_heap::nt_intersection &&
+ m_cur_pi->get_next()->type == Gcalc_heap::nt_intersection &&
+ m_cur_pi->equal_intersection)
+ GCALC_DBUG_ASSERT(cmp_intersections(m_cur_pi, m_cur_pi->get_next()) == 0);
+#endif /*GCALC_DBUG_OFF*/
+ GCALC_DBUG_CHECK_COUNTER();
+ GCALC_DBUG_PRINT_SLICE("step:", state.slice);
+ GCALC_DBUG_PRINT_PI(m_cur_pi);
+ if (m_cur_pi->type == Gcalc_heap::nt_shape_node)
+ {
+ if (m_cur_pi->is_top())
+ {
+ result= insert_top_node();
+ if (!m_cur_pi->is_bottom())
+ do_sorting++;
+ }
+ else if (m_cur_pi->is_bottom())
+ remove_bottom_node();
+ else
+ {
+ do_sorting++;
+ result= node_scan();
+ }
+ if (result)
+ GCALC_DBUG_RETURN(result);
+ state.pi= m_cur_pi;
+ }
+ else if (m_cur_pi->type == Gcalc_heap::nt_eq_node)
+ {
+ do_sorting++;
+ eq_scan();
+ }
+ else
+ {
+ /* nt_intersection */
+ do_sorting++;
+ n_intersections++;
+ intersection_scan();
+ if (!state.pi || state.pi->type == Gcalc_heap::nt_intersection)
+ state.pi= m_cur_pi;
+ }
+
+ m_cur_pi= m_cur_pi->get_next();
+ } while (m_cur_pi && state.pi->equal_pi(m_cur_pi));
+
+ GCALC_DBUG_RETURN(arrange_event(do_sorting, n_intersections));
+}
+
+
+static int node_on_right(const Gcalc_heap::Info *node,
+ const Gcalc_heap::Info *edge_a, const Gcalc_heap::Info *edge_b)
+{
+ Gcalc_coord1 a_x, a_y;
+ Gcalc_coord1 b_x, b_y;
+ Gcalc_coord2 ax_by, ay_bx;
+ int result;
+
+ gcalc_sub_coord1(a_x, node->ix, edge_a->ix);
+ gcalc_sub_coord1(a_y, node->iy, edge_a->iy);
+ gcalc_sub_coord1(b_x, edge_b->ix, edge_a->ix);
+ gcalc_sub_coord1(b_y, edge_b->iy, edge_a->iy);
+ gcalc_mul_coord1(ax_by, a_x, b_y);
+ gcalc_mul_coord1(ay_bx, a_y, b_x);
+ result= gcalc_cmp_coord(ax_by, ay_bx, GCALC_COORD_BASE2);
+#ifdef GCALC_CHECK_WITH_FLOAT
+ {
+ long double dx= gcalc_get_double(edge_b->ix, GCALC_COORD_BASE) -
+ gcalc_get_double(edge_a->ix, GCALC_COORD_BASE);
+ long double dy= gcalc_get_double(edge_b->iy, GCALC_COORD_BASE) -
+ gcalc_get_double(edge_a->iy, GCALC_COORD_BASE);
+ long double ax= gcalc_get_double(node->ix, GCALC_COORD_BASE) -
+ gcalc_get_double(edge_a->ix, GCALC_COORD_BASE);
+ long double ay= gcalc_get_double(node->iy, GCALC_COORD_BASE) -
+ gcalc_get_double(edge_a->iy, GCALC_COORD_BASE);
+ long double d= ax * dy - ay * dx;
+ if (result == 0)
+ GCALC_DBUG_ASSERT(de_check(d, 0.0));
+ else if (result < 0)
+ GCALC_DBUG_ASSERT(de_check(d, 0.0) || d < 0);
+ else
+ GCALC_DBUG_ASSERT(de_check(d, 0.0) || d > 0);
+ }
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+ return result;
+}
+
+
+static int cmp_tops(const Gcalc_heap::Info *top_node,
+ const Gcalc_heap::Info *edge_a, const Gcalc_heap::Info *edge_b)
+{
+ int cmp_res_a, cmp_res_b;
+
+ cmp_res_a= gcalc_cmp_coord1(edge_a->ix, top_node->ix);
+ cmp_res_b= gcalc_cmp_coord1(edge_b->ix, top_node->ix);
+
+ if (cmp_res_a <= 0 && cmp_res_b > 0)
+ return -1;
+ if (cmp_res_b <= 0 && cmp_res_a > 0)
+ return 1;
+ if (cmp_res_a == 0 && cmp_res_b == 0)
+ return 0;
+
+ return node_on_right(edge_a, top_node, edge_b);
+}
+
+
+int Gcalc_scan_iterator::insert_top_node()
+{
+ point *sp= state.slice;
+ point **prev_hook= &state.slice;
+ point *sp1= NULL;
+ point *sp0= new_slice_point();
+ int cmp_res;
+
+ GCALC_DBUG_ENTER("Gcalc_scan_iterator::insert_top_node");
+ if (!sp0)
+ GCALC_DBUG_RETURN(1);
+ sp0->pi= m_cur_pi;
+ sp0->next_pi= m_cur_pi->left;
+#ifndef GCALC_DBUG_OFF
+ sp0->thread= m_cur_thread++;
+#endif /*GCALC_DBUG_OFF*/
+ if (m_cur_pi->left)
+ {
+ calc_dx_dy(sp0);
+ if (m_cur_pi->right)
+ {
+ if (!(sp1= new_slice_point()))
+ GCALC_DBUG_RETURN(1);
+ sp1->event= sp0->event= scev_two_threads;
+ sp1->pi= m_cur_pi;
+ sp1->next_pi= m_cur_pi->right;
+#ifndef GCALC_DBUG_OFF
+ sp1->thread= m_cur_thread++;
+#endif /*GCALC_DBUG_OFF*/
+ calc_dx_dy(sp1);
+ /* We have two threads so should decide which one will be first */
+ cmp_res= cmp_tops(m_cur_pi, m_cur_pi->left, m_cur_pi->right);
+ if (cmp_res > 0)
+ {
+ point *tmp= sp0;
+ sp0= sp1;
+ sp1= tmp;
+ }
+ else if (cmp_res == 0)
+ {
+ /* Exactly same direction of the edges. */
+ cmp_res= gcalc_cmp_coord1(m_cur_pi->left->iy, m_cur_pi->right->iy);
+ if (cmp_res != 0)
+ {
+ if (cmp_res < 0)
+ {
+ if (add_eq_node(sp0->next_pi, sp1))
+ GCALC_DBUG_RETURN(1);
+ }
+ else
+ {
+ if (add_eq_node(sp1->next_pi, sp0))
+ GCALC_DBUG_RETURN(1);
+ }
+ }
+ else
+ {
+ cmp_res= gcalc_cmp_coord1(m_cur_pi->left->ix, m_cur_pi->right->ix);
+ if (cmp_res != 0)
+ {
+ if (cmp_res < 0)
+ {
+ if (add_eq_node(sp0->next_pi, sp1))
+ GCALC_DBUG_RETURN(1);
+ }
+ else
+ {
+ if (add_eq_node(sp1->next_pi, sp0))
+ GCALC_DBUG_RETURN(1);
+ }
+ }
+ }
+ }
+ }
+ else
+ sp0->event= scev_thread;
+ }
+ else
+ sp0->event= scev_single_point;
+
+
+ /* Check if we already have an event - then we'll place the node there */
+ for (; sp && !sp->event; prev_hook= sp->next_ptr(), sp=sp->get_next())
+ {}
+ if (!sp)
+ {
+ sp= state.slice;
+ prev_hook= &state.slice;
+ /* We need to find the place to insert. */
+ for (; sp; prev_hook= sp->next_ptr(), sp=sp->get_next())
+ {
+ if (sp->event || gcalc_cmp_coord1(*sp->r_border, m_cur_pi->ix) < 0)
+ continue;
+ cmp_res= node_on_right(m_cur_pi, sp->pi, sp->next_pi);
+ if (cmp_res == 0)
+ {
+ /* The top node lies on the edge. */
+ /* Nodes of that edge will be handled in other places. */
+ sp->event= scev_intersection;
+ }
+ else if (cmp_res < 0)
+ break;
+ }
+ }
+
+ if (sp0->event == scev_single_point)
+ {
+ /* Add single point to the bottom list. */
+ *m_bottom_hook= sp0;
+ m_bottom_hook= sp0->next_ptr();
+ state.event_position_hook= prev_hook;
+ }
+ else
+ {
+ *prev_hook= sp0;
+ sp0->next= sp;
+ if (add_events_for_node(sp0))
+ GCALC_DBUG_RETURN(1);
+
+ if (sp0->event == scev_two_threads)
+ {
+ *prev_hook= sp1;
+ sp1->next= sp;
+ if (add_events_for_node(sp1))
+ GCALC_DBUG_RETURN(1);
+
+ sp0->next= sp1;
+ *prev_hook= sp0;
+ }
+ }
+
+ GCALC_DBUG_RETURN(0);
+}
+
+
+void Gcalc_scan_iterator::remove_bottom_node()
+{
+ point *sp= state.slice;
+ point **sp_hook= &state.slice;
+ point *first_bottom_point= NULL;
+
+ GCALC_DBUG_ENTER("Gcalc_scan_iterator::remove_bottom_node");
+ for (; sp; sp= sp->get_next())
+ {
+ if (sp->next_pi == m_cur_pi)
+ {
+ *sp_hook= sp->get_next();
+ sp->pi= m_cur_pi;
+ sp->next_pi= NULL;
+ if (first_bottom_point)
+ {
+ first_bottom_point->event= sp->event= scev_two_ends;
+ break;
+ }
+ first_bottom_point= sp;
+ sp->event= scev_end;
+ state.event_position_hook= sp_hook;
+ }
+ else
+ sp_hook= sp->next_ptr();
+ }
+ GCALC_DBUG_ASSERT(first_bottom_point);
+ *m_bottom_hook= first_bottom_point;
+ m_bottom_hook= first_bottom_point->next_ptr();
+ if (sp)
+ {
+ *m_bottom_hook= sp;
+ m_bottom_hook= sp->next_ptr();
+ }
+
+ GCALC_DBUG_VOID_RETURN;
+}
+
+
+int Gcalc_scan_iterator::add_events_for_node(point *sp_node)
+{
+ point *sp= state.slice;
+ int cur_pi_r, sp_pi_r;
+
+ GCALC_DBUG_ENTER("Gcalc_scan_iterator::add_events_for_node");
+
+ /* Scan to the event point. */
+ for (; sp != sp_node; sp= sp->get_next())
+ {
+ GCALC_DBUG_ASSERT(!sp->is_bottom());
+ GCALC_DBUG_PRINT(("left cut_edge %d", sp->thread));
+ if (sp->next_pi == sp_node->next_pi ||
+ gcalc_cmp_coord1(*sp->r_border, *sp_node->l_border) < 0)
+ continue;
+ sp_pi_r= node_on_right(sp->next_pi, sp_node->pi, sp_node->next_pi);
+ if (sp_pi_r < 0)
+ continue;
+ cur_pi_r= node_on_right(sp_node->next_pi, sp->pi, sp->next_pi);
+ if (cur_pi_r > 0)
+ continue;
+ if (cur_pi_r == 0 && sp_pi_r == 0)
+ {
+ int cmp_res= cmp_point_info(sp->next_pi, sp_node->next_pi);
+ if (cmp_res > 0)
+ {
+ if (add_eq_node(sp_node->next_pi, sp))
+ GCALC_DBUG_RETURN(1);
+ }
+ else if (cmp_res < 0)
+ {
+ if (add_eq_node(sp->next_pi, sp_node))
+ GCALC_DBUG_RETURN(1);
+ }
+ continue;
+ }
+
+ if (cur_pi_r == 0)
+ {
+ if (add_eq_node(sp_node->next_pi, sp))
+ GCALC_DBUG_RETURN(1);
+ continue;
+ }
+ else if (sp_pi_r == 0)
+ {
+ if (add_eq_node(sp->next_pi, sp_node))
+ GCALC_DBUG_RETURN(1);
+ continue;
+ }
+
+ if (sp->event)
+ {
+#ifndef GCALC_DBUG_OFF
+ cur_pi_r= node_on_right(sp_node->pi, sp->pi, sp->next_pi);
+ GCALC_DBUG_ASSERT(cur_pi_r == 0);
+#endif /*GCALC_DBUG_OFF*/
+ continue;
+ }
+ cur_pi_r= node_on_right(sp_node->pi, sp->pi, sp->next_pi);
+ GCALC_DBUG_ASSERT(cur_pi_r >= 0);
+ //GCALC_DBUG_ASSERT(cur_pi_r > 0); /* Is it ever violated? */
+ if (cur_pi_r > 0 && add_intersection(sp, sp_node, m_cur_pi))
+ GCALC_DBUG_RETURN(1);
+ }
+
+ /* Scan to the end of the slice */
+ sp= sp->get_next();
+
+ for (; sp; sp= sp->get_next())
+ {
+ GCALC_DBUG_ASSERT(!sp->is_bottom());
+ GCALC_DBUG_PRINT(("right cut_edge %d", sp->thread));
+ if (sp->next_pi == sp_node->next_pi ||
+ gcalc_cmp_coord1(*sp_node->r_border, *sp->l_border) < 0)
+ continue;
+ sp_pi_r= node_on_right(sp->next_pi, sp_node->pi, sp_node->next_pi);
+ if (sp_pi_r > 0)
+ continue;
+ cur_pi_r= node_on_right(sp_node->next_pi, sp->pi, sp->next_pi);
+ if (cur_pi_r < 0)
+ continue;
+ if (cur_pi_r == 0 && sp_pi_r == 0)
+ {
+ int cmp_res= cmp_point_info(sp->next_pi, sp_node->next_pi);
+ if (cmp_res > 0)
+ {
+ if (add_eq_node(sp_node->next_pi, sp))
+ GCALC_DBUG_RETURN(1);
+ }
+ else if (cmp_res < 0)
+ {
+ if (add_eq_node(sp->next_pi, sp_node))
+ GCALC_DBUG_RETURN(1);
+ }
+ continue;
+ }
+ if (cur_pi_r == 0)
+ {
+ if (add_eq_node(sp_node->next_pi, sp))
+ GCALC_DBUG_RETURN(1);
+ continue;
+ }
+ else if (sp_pi_r == 0)
+ {
+ if (add_eq_node(sp->next_pi, sp_node))
+ GCALC_DBUG_RETURN(1);
+ continue;
+ }
+
+ if (sp->event)
+ {
+#ifndef GCALC_DBUG_OFF
+ cur_pi_r= node_on_right(sp_node->pi, sp->pi, sp->next_pi);
+ GCALC_DBUG_ASSERT(cur_pi_r == 0);
+#endif /*GCALC_DBUG_OFF*/
+ continue;
+ }
+ cur_pi_r= node_on_right(sp_node->pi, sp->pi, sp->next_pi);
+ GCALC_DBUG_ASSERT(cur_pi_r <= 0);
+ //GCALC_DBUG_ASSERT(cur_pi_r < 0); /* Is it ever violated? */
+ if (cur_pi_r < 0 && add_intersection(sp_node, sp, m_cur_pi))
+ GCALC_DBUG_RETURN(1);
+ }
+
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_scan_iterator::node_scan()
+{
+ point *sp= state.slice;
+ Gcalc_heap::Info *cur_pi= m_cur_pi;
+
+ GCALC_DBUG_ENTER("Gcalc_scan_iterator::node_scan");
+
+ /* Scan to the event point. */
+ /* Can be avoided if we add link to the sp to the Info. */
+ for (; sp->next_pi != cur_pi; sp= sp->get_next())
+ {}
+
+ GCALC_DBUG_PRINT(("node for %d", sp->thread));
+ /* Handle the point itself. */
+ sp->pi= cur_pi;
+ sp->next_pi= cur_pi->left;
+ sp->event= scev_point;
+ calc_dx_dy(sp);
+
+ GCALC_DBUG_RETURN(add_events_for_node(sp));
+}
+
+
+void Gcalc_scan_iterator::eq_scan()
+{
+ point *sp= eq_sp(m_cur_pi);
+ GCALC_DBUG_ENTER("Gcalc_scan_iterator::eq_scan");
+
+#ifndef GCALC_DBUG_OFF
+ {
+ point *cur_p= state.slice;
+ for (; cur_p && cur_p != sp; cur_p= cur_p->get_next())
+ {}
+ GCALC_DBUG_ASSERT(cur_p);
+ }
+#endif /*GCALC_DBUG_OFF*/
+ if (!sp->event)
+ {
+ sp->event= scev_intersection;
+ sp->ev_pi= m_cur_pi;
+ }
+
+ GCALC_DBUG_VOID_RETURN;
+}
+
+
+void Gcalc_scan_iterator::intersection_scan()
+{
+ intersection_info *ii= i_data(m_cur_pi);
+ GCALC_DBUG_ENTER("Gcalc_scan_iterator::intersection_scan");
+
+#ifndef GCALC_DBUG_OFF
+ {
+ point *sp= state.slice;
+ for (; sp && sp != ii->edge_a; sp= sp->get_next())
+ {}
+ GCALC_DBUG_ASSERT(sp);
+ for (; sp && sp != ii->edge_b; sp= sp->get_next())
+ {}
+ GCALC_DBUG_ASSERT(sp);
+ }
+#endif /*GCALC_DBUG_OFF*/
+
+ ii->edge_a->event= ii->edge_b->event= scev_intersection;
+ ii->edge_a->ev_pi= ii->edge_b->ev_pi= m_cur_pi;
+ free_item(ii);
+ m_cur_pi->intersection_data= NULL;
+
+ GCALC_DBUG_VOID_RETURN;
+}
+
+
+int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b,
+ Gcalc_heap::Info *pi_from)
+{
+ Gcalc_heap::Info *ii;
+ intersection_info *i_calc;
+ int cmp_res;
+ int skip_next= 0;
+
+ GCALC_DBUG_ENTER("Gcalc_scan_iterator::add_intersection");
+ if (!(i_calc= new_intersection_info(sp_a, sp_b)) ||
+ !(ii= new_intersection(m_heap, i_calc)))
+ GCALC_DBUG_RETURN(1);
+
+ ii->equal_intersection= 0;
+
+ for (;
+ pi_from->get_next() != sp_a->next_pi &&
+ pi_from->get_next() != sp_b->next_pi;
+ pi_from= pi_from->get_next())
+ {
+ Gcalc_heap::Info *cur= pi_from->get_next();
+ if (skip_next)
+ {
+ if (cur->type == Gcalc_heap::nt_intersection)
+ skip_next= cur->equal_intersection;
+ else
+ skip_next= 0;
+ continue;
+ }
+ if (cur->type == Gcalc_heap::nt_intersection)
+ {
+ cmp_res= cmp_intersections(cur, ii);
+ skip_next= cur->equal_intersection;
+ }
+ else if (cur->type == Gcalc_heap::nt_eq_node)
+ continue;
+ else
+ cmp_res= cmp_node_isc(cur, ii);
+ if (cmp_res == 0)
+ {
+ ii->equal_intersection= 1;
+ break;
+ }
+ else if (cmp_res > 0)
+ break;
+ }
+
+ /* Intersection inserted before the equal point. */
+ ii->next= pi_from->get_next();
+ pi_from->next= ii;
+
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_scan_iterator::add_eq_node(Gcalc_heap::Info *node, point *sp)
+{
+ Gcalc_heap::Info *en;
+
+ GCALC_DBUG_ENTER("Gcalc_scan_iterator::add_intersection");
+ en= new_eq_point(m_heap, node, sp);
+ if (!en)
+ GCALC_DBUG_RETURN(1);
+
+ /* eq_node iserted after teh equal point. */
+ en->next= node->get_next();
+ node->next= en;
+
+ GCALC_DBUG_RETURN(0);
+}
+
+
+void calc_t(Gcalc_coord2 t_a, Gcalc_coord2 t_b,
+ Gcalc_coord1 dxa, Gcalc_coord1 dxb,
+ const Gcalc_heap::Info *p1, const Gcalc_heap::Info *p2,
+ const Gcalc_heap::Info *p3, const Gcalc_heap::Info *p4)
+{
+ Gcalc_coord1 a2_a1x, a2_a1y;
+ Gcalc_coord2 x1y2, x2y1;
+ Gcalc_coord1 dya, dyb;
+
+ gcalc_sub_coord1(a2_a1x, p3->ix, p1->ix);
+ gcalc_sub_coord1(a2_a1y, p3->iy, p1->iy);
+
+ gcalc_sub_coord1(dxa, p2->ix, p1->ix);
+ gcalc_sub_coord1(dya, p2->iy, p1->iy);
+ gcalc_sub_coord1(dxb, p4->ix, p3->ix);
+ gcalc_sub_coord1(dyb, p4->iy, p3->iy);
+
+ gcalc_mul_coord1(x1y2, dxa, dyb);
+ gcalc_mul_coord1(x2y1, dya, dxb);
+ gcalc_sub_coord(t_b, GCALC_COORD_BASE2, x1y2, x2y1);
+
+
+ gcalc_mul_coord1(x1y2, a2_a1x, dyb);
+ gcalc_mul_coord1(x2y1, a2_a1y, dxb);
+ gcalc_sub_coord(t_a, GCALC_COORD_BASE2, x1y2, x2y1);
+}
+
+
+double Gcalc_scan_iterator::get_y() const
+{
+ if (state.pi->type == Gcalc_heap::nt_intersection)
+ {
+ Gcalc_coord1 dxa, dya;
+ Gcalc_coord2 t_a, t_b;
+ Gcalc_coord3 a_tb, b_ta, y_exp;
+ calc_t(t_a, t_b, dxa, dya,
+ state.pi->p1, state.pi->p2, state.pi->p3, state.pi->p4);
+
+
+ gcalc_mul_coord(a_tb, GCALC_COORD_BASE3,
+ t_b, GCALC_COORD_BASE2, state.pi->p1->iy, GCALC_COORD_BASE);
+ gcalc_mul_coord(b_ta, GCALC_COORD_BASE3,
+ t_a, GCALC_COORD_BASE2, dya, GCALC_COORD_BASE);
+
+ gcalc_add_coord(y_exp, GCALC_COORD_BASE3, a_tb, b_ta);
+
+ return (get_pure_double(y_exp, GCALC_COORD_BASE3) /
+ get_pure_double(t_b, GCALC_COORD_BASE2)) / m_heap->coord_extent;
+ }
+ else
+ return state.pi->y;
+}
+
+
+double Gcalc_scan_iterator::get_event_x() const
+{
+ if (state.pi->type == Gcalc_heap::nt_intersection)
+ {
+ Gcalc_coord1 dxa, dya;
+ Gcalc_coord2 t_a, t_b;
+ Gcalc_coord3 a_tb, b_ta, x_exp;
+ calc_t(t_a, t_b, dxa, dya,
+ state.pi->p1, state.pi->p2, state.pi->p3, state.pi->p4);
+
+
+ gcalc_mul_coord(a_tb, GCALC_COORD_BASE3,
+ t_b, GCALC_COORD_BASE2, state.pi->p1->ix, GCALC_COORD_BASE);
+ gcalc_mul_coord(b_ta, GCALC_COORD_BASE3,
+ t_a, GCALC_COORD_BASE2, dxa, GCALC_COORD_BASE);
+
+ gcalc_add_coord(x_exp, GCALC_COORD_BASE3, a_tb, b_ta);
+
+ return (get_pure_double(x_exp, GCALC_COORD_BASE3) /
+ get_pure_double(t_b, GCALC_COORD_BASE2)) / m_heap->coord_extent;
+ }
+ else
+ return state.pi->x;
+}
+
+double Gcalc_scan_iterator::get_h() const
+{
+ double cur_y= get_y();
+ double next_y;
+ if (state.pi->type == Gcalc_heap::nt_intersection)
+ {
+ double x;
+ state.pi->calc_xy(&x, &next_y);
+ }
+ else
+ next_y= state.pi->y;
+ return next_y - cur_y;
+}
+
+
+double Gcalc_scan_iterator::get_sp_x(const point *sp) const
+{
+ double dy;
+ if (sp->event & (scev_end | scev_two_ends | scev_point))
+ return sp->pi->x;
+ dy= sp->next_pi->y - sp->pi->y;
+ if (fabs(dy) < 1e-12)
+ return sp->pi->x;
+ return (sp->next_pi->x - sp->pi->x) * dy;
+}
+
+
+double Gcalc_scan_iterator::get_pure_double(const Gcalc_internal_coord *d,
+ int d_len)
+{
+ int n= 1;
+ long double res= (long double) FIRST_DIGIT(d[0]);
+ do
+ {
+ res*= (long double) GCALC_DIG_BASE;
+ res+= (long double) d[n];
+ } while(++n < d_len);
+
+ if (GCALC_SIGN(d[0]))
+ res*= -1.0;
+ return res;
+}
+
+
+#endif /* HAVE_SPATIAL */
diff --git a/sql/gcalc_slicescan.h b/sql/gcalc_slicescan.h
new file mode 100644
index 00000000000..9fc4cea5199
--- /dev/null
+++ b/sql/gcalc_slicescan.h
@@ -0,0 +1,595 @@
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+ Copyright (C) 2011 Monty Program Ab.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#ifndef GCALC_SLICESCAN_INCLUDED
+#define GCALC_SLICESCAN_INCLUDED
+
+#ifndef DBUG_OFF
+// #define GCALC_CHECK_WITH_FLOAT
+#else
+#define GCALC_DBUG_OFF
+#endif /*DBUG_OFF*/
+
+#ifndef GCALC_DBUG_OFF
+#define GCALC_DBUG_PRINT(b) DBUG_PRINT("Gcalc", b)
+#define GCALC_DBUG_ENTER(a) DBUG_ENTER("Gcalc "a)
+#define GCALC_DBUG_RETURN(r) DBUG_RETURN(r)
+#define GCALC_DBUG_VOID_RETURN DBUG_VOID_RETURN
+#define GCALC_DBUG_ASSERT(r) DBUG_ASSERT(r)
+#else
+#define GCALC_DBUG_PRINT(b) do {} while(0)
+#define GCALC_DBUG_ENTER(a) do {} while(0)
+#define GCALC_DBUG_RETURN(r) return (r)
+#define GCALC_DBUG_VOID_RETURN do {} while(0)
+#define GCALC_DBUG_ASSERT(r) do {} while(0)
+#endif /*GCALC_DBUG_OFF*/
+
+#define GCALC_TERMINATED(state_var) (state_var && (*state_var))
+#define GCALC_SET_TERMINATED(state_var, val) state_var= val
+#define GCALC_DECL_TERMINATED_STATE(varname) \
+ volatile int *varname;
+
+/*
+ Gcalc_dyn_list class designed to manage long lists of same-size objects
+ with the possible efficiency.
+ It allocates fixed-size blocks of memory (blk_size specified at the time
+ of creation). When new object is added to the list, it occupies part of
+ this block until it's full. Then the new block is allocated.
+ Freed objects are chained to the m_free list, and if it's not empty, the
+ newly added object is taken from this list instead the block.
+*/
+
+class Gcalc_dyn_list
+{
+public:
+ class Item
+ {
+ public:
+ Item *next;
+ };
+
+ Gcalc_dyn_list(size_t blk_size, size_t sizeof_item);
+ ~Gcalc_dyn_list();
+ Item *new_item()
+ {
+ Item *result;
+ if (m_free)
+ {
+ result= m_free;
+ m_free= m_free->next;
+ }
+ else
+ result= alloc_new_blk();
+
+ return result;
+ }
+ inline void free_item(Item *item)
+ {
+ item->next= m_free;
+ m_free= item;
+ }
+ inline void free_list(Item **list, Item **hook)
+ {
+ *hook= m_free;
+ m_free= *list;
+ }
+
+ void free_list(Item *list)
+ {
+ Item **hook= &list;
+ while (*hook)
+ hook= &(*hook)->next;
+ free_list(&list, hook);
+ }
+
+ void reset();
+ void cleanup();
+
+protected:
+ size_t m_blk_size;
+ size_t m_sizeof_item;
+ unsigned int m_points_per_blk;
+ void *m_first_blk;
+ void **m_blk_hook;
+ Item *m_free;
+ Item *m_keep;
+
+ Item *alloc_new_blk();
+ void format_blk(void* block);
+ inline Item *ptr_add(Item *ptr, int n_items)
+ {
+ return (Item *)(((char*)ptr) + n_items * m_sizeof_item);
+ }
+};
+
+/* Internal Gcalc coordinates to provide the precise calculations */
+
+#define GCALC_DIG_BASE 1000000000
+typedef uint32 gcalc_digit_t;
+typedef unsigned long long gcalc_coord2;
+typedef gcalc_digit_t Gcalc_internal_coord;
+#define GCALC_COORD_BASE 2
+#define GCALC_COORD_BASE2 4
+#define GCALC_COORD_BASE3 6
+#define GCALC_COORD_BASE4 8
+#define GCALC_COORD_BASE5 10
+
+typedef gcalc_digit_t Gcalc_coord1[GCALC_COORD_BASE];
+typedef gcalc_digit_t Gcalc_coord2[GCALC_COORD_BASE*2];
+typedef gcalc_digit_t Gcalc_coord3[GCALC_COORD_BASE*3];
+
+
+void gcalc_mul_coord(Gcalc_internal_coord *result, int result_len,
+ const Gcalc_internal_coord *a, int a_len,
+ const Gcalc_internal_coord *b, int b_len);
+
+void gcalc_add_coord(Gcalc_internal_coord *result, int result_len,
+ const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b);
+
+void gcalc_sub_coord(Gcalc_internal_coord *result, int result_len,
+ const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b);
+
+int gcalc_cmp_coord(const Gcalc_internal_coord *a,
+ const Gcalc_internal_coord *b, int len);
+
+/* Internal coordinates declarations end. */
+
+
+typedef uint gcalc_shape_info;
+
+/*
+ Gcalc_heap represents the 'dynamic list' of Info objects, that
+ contain information about vertexes of all the shapes that take
+ part in some spatial calculation. Can become quite long.
+ After filled, the list is usually sorted and then walked through
+ in the slicescan algorithm.
+ The Gcalc_heap and the algorithm can only operate with two
+ kinds of shapes - polygon and polyline. So all the spatial
+ objects should be represented as sets of these two.
+*/
+
+class Gcalc_heap : public Gcalc_dyn_list
+{
+public:
+ enum node_type
+ {
+ nt_shape_node,
+ nt_intersection,
+ nt_eq_node
+ };
+ class Info : public Gcalc_dyn_list::Item
+ {
+ public:
+ node_type type;
+ union
+ {
+ struct
+ {
+ /* nt_shape_node */
+ gcalc_shape_info shape;
+ Info *left;
+ Info *right;
+ double x,y;
+ Gcalc_coord1 ix, iy;
+ int top_node;
+ };
+ struct
+ {
+ /* nt_intersection */
+ /* Line p1-p2 supposed to intersect line p3-p4 */
+ const Info *p1;
+ const Info *p2;
+ const Info *p3;
+ const Info *p4;
+ void *intersection_data;
+ int equal_intersection;
+ };
+ struct
+ {
+ /* nt_eq_node */
+ const Info *node;
+ void *eq_data;
+ };
+ };
+
+ bool is_bottom() const
+ { GCALC_DBUG_ASSERT(type == nt_shape_node); return !left; }
+ bool is_top() const
+ { GCALC_DBUG_ASSERT(type == nt_shape_node); return top_node; }
+ bool is_single_node() const
+ { return is_bottom() && is_top(); }
+
+ void calc_xy(double *x, double *y) const;
+ int equal_pi(const Info *pi) const;
+#ifdef GCALC_CHECK_WITH_FLOAT
+ void calc_xy_ld(long double *x, long double *y) const;
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+
+ Info *get_next() { return (Info *)next; }
+ const Info *get_next() const { return (const Info *)next; }
+ };
+
+ Gcalc_heap(size_t blk_size=8192) :
+ Gcalc_dyn_list(blk_size, sizeof(Info)),
+ m_hook(&m_first), m_n_points(0)
+ {}
+ Info *new_point_info(double x, double y, gcalc_shape_info shape);
+ Info *new_intersection(const Info *p1, const Info *p2,
+ const Info *p3, const Info *p4);
+ void prepare_operation();
+ inline bool ready() const { return m_hook == NULL; }
+ Info *get_first() { return (Info *)m_first; }
+ const Info *get_first() const { return (const Info *)m_first; }
+ Gcalc_dyn_list::Item **get_last_hook() { return m_hook; }
+ void reset();
+#ifdef GCALC_CHECK_WITH_FLOAT
+ long double get_double(const Gcalc_internal_coord *c) const;
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+ double coord_extent;
+private:
+ Gcalc_dyn_list::Item *m_first;
+ Gcalc_dyn_list::Item **m_hook;
+ int m_n_points;
+};
+
+
+/*
+ the spatial object has to be represented as a set of
+ simple polygones and polylines to be sent to the slicescan.
+
+ Gcalc_shape_transporter class and his descendants are used to
+ simplify storing the information about the shape into necessary structures.
+ This base class only fills the Gcalc_heap with the information about
+ shapes and vertices.
+
+ Normally the Gcalc_shape_transporter family object is sent as a parameter
+ to the 'get_shapes' method of an 'spatial' object so it can pass
+ the spatial information about itself. The virtual methods are
+ treating this data in a way the caller needs.
+*/
+
+class Gcalc_shape_transporter
+{
+private:
+ Gcalc_heap::Info *m_first;
+ Gcalc_heap::Info *m_prev;
+ int m_shape_started;
+ void int_complete();
+protected:
+ Gcalc_heap *m_heap;
+ int int_single_point(gcalc_shape_info Info, double x, double y);
+ int int_add_point(gcalc_shape_info Info, double x, double y);
+ void int_start_line()
+ {
+ DBUG_ASSERT(!m_shape_started);
+ m_shape_started= 1;
+ m_first= m_prev= NULL;
+ }
+ void int_complete_line()
+ {
+ DBUG_ASSERT(m_shape_started== 1);
+ int_complete();
+ m_shape_started= 0;
+ }
+ void int_start_ring()
+ {
+ DBUG_ASSERT(m_shape_started== 2);
+ m_shape_started= 3;
+ m_first= m_prev= NULL;
+ }
+ void int_complete_ring()
+ {
+ DBUG_ASSERT(m_shape_started== 3);
+ int_complete();
+ m_shape_started= 2;
+ }
+ void int_start_poly()
+ {
+ DBUG_ASSERT(!m_shape_started);
+ m_shape_started= 2;
+ }
+ void int_complete_poly()
+ {
+ DBUG_ASSERT(m_shape_started== 2);
+ m_shape_started= 0;
+ }
+ bool line_started() { return m_shape_started == 1; };
+public:
+ Gcalc_shape_transporter(Gcalc_heap *heap) :
+ m_shape_started(0), m_heap(heap) {}
+
+ virtual int single_point(double x, double y)=0;
+ virtual int start_line()=0;
+ virtual int complete_line()=0;
+ virtual int start_poly()=0;
+ virtual int complete_poly()=0;
+ virtual int start_ring()=0;
+ virtual int complete_ring()=0;
+ virtual int add_point(double x, double y)=0;
+ virtual int start_collection(int n_objects) { return 0; }
+ virtual int empty_shape() { return 0; }
+ int start_simple_poly()
+ {
+ return start_poly() || start_ring();
+ }
+ int complete_simple_poly()
+ {
+ return complete_ring() || complete_poly();
+ }
+ virtual ~Gcalc_shape_transporter() {}
+};
+
+
+enum Gcalc_scan_events
+{
+ scev_none= 0,
+ scev_point= 1, /* Just a new point in thread */
+ scev_thread= 2, /* Start of the new thread */
+ scev_two_threads= 4, /* A couple of new threads started */
+ scev_intersection= 8, /* Intersection happened */
+ scev_end= 16, /* Single thread finished */
+ scev_two_ends= 32, /* A couple of threads finished */
+ scev_single_point= 64 /* Got single point */
+};
+
+
+/*
+ Gcalc_scan_iterator incapsulates the slisescan algorithm.
+ It takes filled Gcalc_heap as an datasource. Then can be
+ iterated trought the vertexes and intersection points with
+ the step() method. After the 'step()' one usually observes
+ the current 'slice' to do the necessary calculations, like
+ looking for intersections, calculating the area, whatever.
+*/
+
+class Gcalc_scan_iterator : public Gcalc_dyn_list
+{
+public:
+ class point : public Gcalc_dyn_list::Item
+ {
+ public:
+ Gcalc_coord1 dx;
+ Gcalc_coord1 dy;
+ Gcalc_heap::Info *pi;
+ Gcalc_heap::Info *next_pi;
+ Gcalc_heap::Info *ev_pi;
+ const Gcalc_coord1 *l_border;
+ const Gcalc_coord1 *r_border;
+ point *ev_next;
+
+ Gcalc_scan_events event;
+
+ inline const point *c_get_next() const
+ { return (const point *)next; }
+ inline bool is_bottom() const { return !next_pi; }
+ gcalc_shape_info get_shape() const { return pi->shape; }
+ inline point *get_next() { return (point *)next; }
+ inline const point *get_next() const { return (const point *)next; }
+ /* Compare the dx_dy parameters regarding the horiz_dir */
+ /* returns -1 if less, 0 if equal, 1 if bigger */
+ static int cmp_dx_dy(const Gcalc_coord1 dx_a,
+ const Gcalc_coord1 dy_a,
+ const Gcalc_coord1 dx_b,
+ const Gcalc_coord1 dy_b);
+ static int cmp_dx_dy(const Gcalc_heap::Info *p1,
+ const Gcalc_heap::Info *p2,
+ const Gcalc_heap::Info *p3,
+ const Gcalc_heap::Info *p4);
+ int cmp_dx_dy(const point *p) const;
+ point **next_ptr() { return (point **) &next; }
+#ifndef GCALC_DBUG_OFF
+ unsigned int thread;
+#endif /*GCALC_DBUG_OFF*/
+#ifdef GCALC_CHECK_WITH_FLOAT
+ void calc_x(long double *x, long double y, long double ix) const;
+#endif /*GCALC_CHECK_WITH_FLOAT*/
+ };
+
+ /* That class introduced mostly for the 'typecontrol' reason. */
+ /* only difference from the point classis the get_next() function. */
+ class event_point : public point
+ {
+ public:
+ inline const event_point *get_next() const
+ { return (const event_point*) ev_next; }
+ int simple_event() const
+ {
+ return !ev_next ? (event & (scev_point | scev_end)) :
+ (!ev_next->ev_next && event == scev_two_ends);
+ }
+ };
+
+ class intersection_info : public Gcalc_dyn_list::Item
+ {
+ public:
+ point *edge_a;
+ point *edge_b;
+
+ Gcalc_coord2 t_a;
+ Gcalc_coord2 t_b;
+ int t_calculated;
+ Gcalc_coord3 x_exp;
+ int x_calculated;
+ Gcalc_coord3 y_exp;
+ int y_calculated;
+ void calc_t()
+ {if (!t_calculated) do_calc_t(); }
+ void calc_y_exp()
+ { if (!y_calculated) do_calc_y(); }
+ void calc_x_exp()
+ { if (!x_calculated) do_calc_x(); }
+
+ void do_calc_t();
+ void do_calc_x();
+ void do_calc_y();
+ };
+
+
+ class slice_state
+ {
+ public:
+ point *slice;
+ point **event_position_hook;
+ point *event_end;
+ const Gcalc_heap::Info *pi;
+ };
+
+public:
+ Gcalc_scan_iterator(size_t blk_size= 8192);
+
+ GCALC_DECL_TERMINATED_STATE(killed)
+
+ void init(Gcalc_heap *points); /* Iterator can be reused */
+ void reset();
+ int step();
+
+ Gcalc_heap::Info *more_points() { return m_cur_pi; }
+ bool more_trapezoids()
+ { return m_cur_pi && m_cur_pi->next; }
+
+ const point *get_bottom_points() const
+ { return m_bottom_points; }
+ const point *get_event_position() const
+ { return *state.event_position_hook; }
+ const point *get_event_end() const
+ { return state.event_end; }
+ const event_point *get_events() const
+ { return (const event_point *)
+ (*state.event_position_hook == state.event_end ?
+ m_bottom_points : *state.event_position_hook); }
+ const point *get_b_slice() const { return state.slice; }
+ double get_h() const;
+ double get_y() const;
+ double get_event_x() const;
+ double get_sp_x(const point *sp) const;
+ int intersection_step() const
+ { return state.pi->type == Gcalc_heap::nt_intersection; }
+ const Gcalc_heap::Info *get_cur_pi() const
+ {
+ return state.pi;
+ }
+
+private:
+ Gcalc_heap *m_heap;
+ Gcalc_heap::Info *m_cur_pi;
+ slice_state state;
+
+#ifndef GCALC_DBUG_OFF
+ unsigned int m_cur_thread;
+#endif /*GCALC_DBUG_OFF*/
+
+ point *m_bottom_points;
+ point **m_bottom_hook;
+
+ int node_scan();
+ void eq_scan();
+ void intersection_scan();
+ void remove_bottom_node();
+ int insert_top_node();
+ int add_intersection(point *sp_a, point *sp_b,
+ Gcalc_heap::Info *pi_from);
+ int add_eq_node(Gcalc_heap::Info *node, point *sp);
+ int add_events_for_node(point *sp_node);
+
+ point *new_slice_point()
+ {
+ point *new_point= (point *)new_item();
+ return new_point;
+ }
+ intersection_info *new_intersection_info(point *a, point *b)
+ {
+ intersection_info *ii= (intersection_info *)new_item();
+ ii->edge_a= a;
+ ii->edge_b= b;
+ ii->t_calculated= ii->x_calculated= ii->y_calculated= 0;
+ return ii;
+ }
+ int arrange_event(int do_sorting, int n_intersections);
+ static double get_pure_double(const Gcalc_internal_coord *d, int d_len);
+};
+
+
+/*
+ Gcalc_trapezoid_iterator simplifies the calculations on
+ the current slice of the Gcalc_scan_iterator.
+ One can walk through the trapezoids formed between
+ previous and current slices.
+*/
+
+#ifdef TMP_BLOCK
+class Gcalc_trapezoid_iterator
+{
+protected:
+ const Gcalc_scan_iterator::point *sp0;
+ const Gcalc_scan_iterator::point *sp1;
+public:
+ Gcalc_trapezoid_iterator(const Gcalc_scan_iterator *scan_i) :
+ sp0(scan_i->get_b_slice()),
+ sp1(scan_i->get_t_slice())
+ {}
+
+ inline bool more() const { return sp1 && sp1->next; }
+
+ const Gcalc_scan_iterator::point *lt() const { return sp1; }
+ const Gcalc_scan_iterator::point *lb() const { return sp0; }
+ const Gcalc_scan_iterator::point *rb() const
+ {
+ const Gcalc_scan_iterator::point *result= sp0;
+ while ((result= result->c_get_next())->is_bottom())
+ {}
+ return result;
+ }
+ const Gcalc_scan_iterator::point *rt() const
+ { return sp1->c_get_next(); }
+
+ void operator++()
+ {
+ sp0= rb();
+ sp1= rt();
+ }
+};
+#endif /*TMP_BLOCK*/
+
+
+/*
+ Gcalc_point_iterator simplifies the calculations on
+ the current slice of the Gcalc_scan_iterator.
+ One can walk through the points on the current slice.
+*/
+
+class Gcalc_point_iterator
+{
+protected:
+ const Gcalc_scan_iterator::point *sp;
+public:
+ Gcalc_point_iterator(const Gcalc_scan_iterator *scan_i):
+ sp(scan_i->get_b_slice())
+ {}
+
+ inline bool more() const { return sp != NULL; }
+ inline void operator++() { sp= sp->c_get_next(); }
+ inline const Gcalc_scan_iterator::point *point() const { return sp; }
+ inline const Gcalc_heap::Info *get_pi() const { return sp->pi; }
+ inline gcalc_shape_info get_shape() const { return sp->get_shape(); }
+ inline void restart(const Gcalc_scan_iterator *scan_i)
+ { sp= scan_i->get_b_slice(); }
+};
+
+#endif /*GCALC_SLICESCAN_INCLUDED*/
+
diff --git a/sql/gcalc_tools.cc b/sql/gcalc_tools.cc
new file mode 100644
index 00000000000..187acbacc4c
--- /dev/null
+++ b/sql/gcalc_tools.cc
@@ -0,0 +1,1429 @@
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+ Copyright (C) 2011 Monty Program Ab.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <my_global.h>
+
+#ifdef HAVE_SPATIAL
+
+#include "gcalc_tools.h"
+#include "spatial.h"
+
+#define float_to_coord(d) ((double) d)
+
+
+/*
+ Adds new shape to the relation.
+ After that it can be used as an argument of an operation.
+*/
+
+gcalc_shape_info Gcalc_function::add_new_shape(uint32 shape_id,
+ shape_type shape_kind)
+{
+ shapes_buffer.q_append((uint32) shape_kind);
+ return n_shapes++;
+}
+
+
+/*
+ Adds new operation to the constructed relation.
+ To construct the complex relation one has to specify operations
+ in prefix style.
+*/
+
+void Gcalc_function::add_operation(uint operation, uint32 n_operands)
+{
+ uint32 op_code= (uint32 ) operation + n_operands;
+ function_buffer.q_append(op_code);
+}
+
+
+/*
+ Sometimes the number of arguments is unknown at the moment the operation
+ is added. That allows to specify it later.
+*/
+
+void Gcalc_function::add_operands_to_op(uint32 operation_pos, uint32 n_operands)
+{
+ uint32 op_code= uint4korr(function_buffer.ptr() + operation_pos) + n_operands;
+ function_buffer.write_at_position(operation_pos, op_code);
+}
+
+
+/*
+ Just like the add_operation() but the result will be the inverted
+ value of an operation.
+*/
+
+void Gcalc_function::add_not_operation(op_type operation, uint32 n_operands)
+{
+ uint32 op_code= ((uint32) op_not | (uint32 ) operation) + n_operands;
+ function_buffer.q_append(op_code);
+}
+
+
+int Gcalc_function::single_shape_op(shape_type shape_kind, gcalc_shape_info *si)
+{
+ if (reserve_shape_buffer(1) || reserve_op_buffer(1))
+ return 1;
+ *si= add_new_shape(0, shape_kind);
+ add_operation(op_shape, *si);
+ return 0;
+}
+
+
+int Gcalc_function::repeat_expression(uint32 exp_pos)
+{
+ if (reserve_op_buffer(1))
+ return 1;
+ add_operation(op_repeat, exp_pos);
+ return 0;
+}
+
+
+/*
+ Specify how many arguments we're going to have.
+*/
+
+int Gcalc_function::reserve_shape_buffer(uint n_shapes)
+{
+ return shapes_buffer.reserve(n_shapes * 4, 512);
+}
+
+
+/*
+ Specify how many operations we're going to have.
+*/
+
+int Gcalc_function::reserve_op_buffer(uint n_ops)
+{
+ return function_buffer.reserve(n_ops * 4, 512);
+}
+
+
+int Gcalc_function::alloc_states()
+{
+ if (function_buffer.reserve((n_shapes+1) * 2 * sizeof(int)))
+ return 1;
+ i_states= (int *) (function_buffer.ptr() + ALIGN_SIZE(function_buffer.length()));
+ b_states= i_states + (n_shapes + 1);
+ return 0;
+}
+
+
+int Gcalc_function::count_internal(const char *cur_func, uint set_type,
+ const char **end)
+{
+ uint c_op= uint4korr(cur_func);
+ op_type next_func= (op_type) (c_op & op_any);
+ int mask= (c_op & op_not) ? 1:0;
+ uint n_ops= c_op & ~(op_any | op_not | v_mask);
+ uint n_shape= c_op & ~(op_any | op_not | v_mask); /* same as n_ops */
+ value v_state= (value) (c_op & v_mask);
+ int result= 0;
+ const char *sav_cur_func= cur_func;
+
+ // GCALC_DBUG_ENTER("Gcalc_function::count_internal");
+
+ cur_func+= 4;
+ if (next_func == op_shape)
+ {
+ if (set_type == 0)
+ result= i_states[n_shape] | b_states[n_shape];
+ else if (set_type == op_border)
+ result= b_states[n_shape];
+ else if (set_type == op_internals)
+ result= i_states[n_shape] && !b_states[n_shape];
+ goto exit;
+ }
+
+ if (next_func == op_false)
+ {
+ result= 0;
+ goto exit;
+ }
+
+ if (next_func == op_border || next_func == op_internals)
+ {
+ result= count_internal(cur_func, next_func, &cur_func);
+ goto exit;
+ }
+
+ if (next_func == op_repeat)
+ {
+ result= count_internal(function_buffer.ptr() + n_ops, set_type, 0);
+ goto exit;
+ }
+
+ if (n_ops == 0)
+ return mask;
+ //GCALC_DBUG_RETURN(mask);
+
+ result= count_internal(cur_func, set_type, &cur_func);
+
+ while (--n_ops)
+ {
+ int next_res= count_internal(cur_func, set_type, &cur_func);
+ switch (next_func)
+ {
+ case op_union:
+ result= result | next_res;
+ break;
+ case op_intersection:
+ result= result & next_res;
+ break;
+ case op_symdifference:
+ result= result ^ next_res;
+ break;
+ case op_difference:
+ result= result & !next_res;
+ break;
+ default:
+ GCALC_DBUG_ASSERT(FALSE);
+ };
+ }
+
+exit:
+ result^= mask;
+ if (v_state != v_empty)
+ {
+ switch (v_state)
+ {
+ case v_find_t:
+ if (result)
+ {
+ c_op= (c_op & ~v_mask) | v_t_found;
+ int4store(sav_cur_func, c_op);
+ };
+ break;
+ case v_find_f:
+ if (!result)
+ {
+ c_op= (c_op & ~v_mask) | v_f_found;
+ int4store(sav_cur_func, c_op);
+ };
+ break;
+ case v_t_found:
+ result= 1;
+ break;
+ case v_f_found:
+ result= 0;
+ break;
+ default:
+ GCALC_DBUG_ASSERT(0);
+ };
+ }
+
+ if (end)
+ *end= cur_func;
+ return result;
+ //GCALC_DBUG_RETURN(result);
+}
+
+
+void Gcalc_function::clear_i_states()
+{
+ for (uint i= 0; i < n_shapes; i++)
+ i_states[i]= 0;
+}
+
+
+void Gcalc_function::clear_b_states()
+{
+ for (uint i= 0; i < n_shapes; i++)
+ b_states[i]= 0;
+}
+
+
+/*
+ Clear the state of the object.
+*/
+
+void Gcalc_function::reset()
+{
+ n_shapes= 0;
+ shapes_buffer.length(0);
+ function_buffer.length(0);
+}
+
+
+int Gcalc_function::check_function(Gcalc_scan_iterator &scan_it)
+{
+ const Gcalc_scan_iterator::point *eq_start, *cur_eq;
+ const Gcalc_scan_iterator::event_point *events;
+ GCALC_DBUG_ENTER("Gcalc_function::check_function");
+
+ while (scan_it.more_points())
+ {
+ if (scan_it.step())
+ GCALC_DBUG_RETURN(-1);
+ events= scan_it.get_events();
+
+ /* these kinds of events don't change the function */
+ Gcalc_point_iterator pit(&scan_it);
+ clear_b_states();
+ clear_i_states();
+ /* Walk to the event, marking polygons we met */
+ for (; pit.point() != scan_it.get_event_position(); ++pit)
+ {
+ gcalc_shape_info si= pit.point()->get_shape();
+ if ((get_shape_kind(si) == Gcalc_function::shape_polygon))
+ invert_i_state(si);
+ }
+ if (events->simple_event())
+ {
+ if (events->event == scev_end)
+ set_b_state(events->get_shape());
+
+ if (count())
+ GCALC_DBUG_RETURN(1);
+ clear_b_states();
+ continue;
+ }
+
+ /* Check the status of the event point */
+ for (; events; events= events->get_next())
+ {
+ gcalc_shape_info si= events->get_shape();
+ if (events->event == scev_thread ||
+ events->event == scev_end ||
+ events->event == scev_single_point ||
+ (get_shape_kind(si) == Gcalc_function::shape_polygon))
+ set_b_state(si);
+ else if (get_shape_kind(si) == Gcalc_function::shape_line)
+ set_i_state(si);
+ }
+
+ if (count())
+ GCALC_DBUG_RETURN(1);
+
+ /* Set back states changed in the loop above. */
+ for (events= scan_it.get_events(); events; events= events->get_next())
+ {
+ gcalc_shape_info si= events->get_shape();
+ if (events->event == scev_thread ||
+ events->event == scev_end ||
+ events->event == scev_single_point ||
+ (get_shape_kind(si) == Gcalc_function::shape_polygon))
+ clear_b_state(si);
+ else if (get_shape_kind(si) == Gcalc_function::shape_line)
+ clear_i_state(si);
+ }
+
+ if (scan_it.get_event_position() == scan_it.get_event_end())
+ continue;
+
+ /* Check the status after the event */
+ eq_start= pit.point();
+ do
+ {
+ ++pit;
+ if (pit.point() != scan_it.get_event_end() &&
+ eq_start->cmp_dx_dy(pit.point()) == 0)
+ continue;
+ for (cur_eq= eq_start; cur_eq != pit.point();
+ cur_eq= cur_eq->get_next())
+ {
+ gcalc_shape_info si= cur_eq->get_shape();
+ if (get_shape_kind(si) == Gcalc_function::shape_polygon)
+ set_b_state(si);
+ else
+ invert_i_state(si);
+ }
+ if (count())
+ GCALC_DBUG_RETURN(1);
+
+ for (cur_eq= eq_start; cur_eq != pit.point(); cur_eq= cur_eq->get_next())
+ {
+ gcalc_shape_info si= cur_eq->get_shape();
+ if ((get_shape_kind(si) == Gcalc_function::shape_polygon))
+ {
+ clear_b_state(si);
+ invert_i_state(si);
+ }
+ else
+ invert_i_state(cur_eq->get_shape());
+ }
+ if (count())
+ GCALC_DBUG_RETURN(1);
+ eq_start= pit.point();
+ } while (pit.point() != scan_it.get_event_end());
+ }
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_transporter::single_point(double x, double y)
+{
+ gcalc_shape_info si;
+ return m_fn->single_shape_op(Gcalc_function::shape_point, &si) ||
+ int_single_point(si, x, y);
+}
+
+
+int Gcalc_operation_transporter::start_line()
+{
+ int_start_line();
+ return m_fn->single_shape_op(Gcalc_function::shape_line, &m_si);
+}
+
+
+int Gcalc_operation_transporter::complete_line()
+{
+ int_complete_line();
+ return 0;
+}
+
+
+int Gcalc_operation_transporter::start_poly()
+{
+ int_start_poly();
+ return m_fn->single_shape_op(Gcalc_function::shape_polygon, &m_si);
+}
+
+
+int Gcalc_operation_transporter::complete_poly()
+{
+ int_complete_poly();
+ return 0;
+}
+
+
+int Gcalc_operation_transporter::start_ring()
+{
+ int_start_ring();
+ return 0;
+}
+
+
+int Gcalc_operation_transporter::complete_ring()
+{
+ int_complete_ring();
+ return 0;
+}
+
+
+int Gcalc_operation_transporter::add_point(double x, double y)
+{
+ return int_add_point(m_si, x, y);
+}
+
+
+int Gcalc_operation_transporter::start_collection(int n_objects)
+{
+ if (m_fn->reserve_shape_buffer(n_objects) || m_fn->reserve_op_buffer(1))
+ return 1;
+ m_fn->add_operation(Gcalc_function::op_union, n_objects);
+ return 0;
+}
+
+
+int Gcalc_operation_transporter::empty_shape()
+{
+ if (m_fn->reserve_op_buffer(1))
+ return 1;
+ m_fn->add_operation(Gcalc_function::op_false, 0);
+ return 0;
+}
+
+
+int Gcalc_result_receiver::start_shape(Gcalc_function::shape_type shape)
+{
+ GCALC_DBUG_ENTER("Gcalc_result_receiver::start_shape");
+ if (buffer.reserve(4*2, 512))
+ GCALC_DBUG_RETURN(1);
+ cur_shape= shape;
+ shape_pos= buffer.length();
+ buffer.length(shape_pos + ((shape == Gcalc_function::shape_point) ? 4:8));
+ n_points= 0;
+ shape_area= 0.0;
+
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_result_receiver::add_point(double x, double y)
+{
+ GCALC_DBUG_ENTER("Gcalc_result_receiver::add_point");
+ if (n_points && x == prev_x && y == prev_y)
+ GCALC_DBUG_RETURN(0);
+
+ if (!n_points++)
+ {
+ prev_x= first_x= x;
+ prev_y= first_y= y;
+ GCALC_DBUG_RETURN(0);
+ }
+
+ shape_area+= prev_x*y - prev_y*x;
+
+ if (buffer.reserve(8*2, 512))
+ GCALC_DBUG_RETURN(1);
+ buffer.q_append(prev_x);
+ buffer.q_append(prev_y);
+ prev_x= x;
+ prev_y= y;
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_result_receiver::complete_shape()
+{
+ GCALC_DBUG_ENTER("Gcalc_result_receiver::complete_shape");
+ if (n_points == 0)
+ {
+ buffer.length(shape_pos);
+ GCALC_DBUG_RETURN(0);
+ }
+ if (n_points == 1)
+ {
+ if (cur_shape != Gcalc_function::shape_point)
+ {
+ if (cur_shape == Gcalc_function::shape_hole)
+ {
+ buffer.length(shape_pos);
+ GCALC_DBUG_RETURN(0);
+ }
+ cur_shape= Gcalc_function::shape_point;
+ buffer.length(buffer.length()-4);
+ }
+ }
+ else
+ {
+ GCALC_DBUG_ASSERT(cur_shape != Gcalc_function::shape_point);
+ if (cur_shape == Gcalc_function::shape_hole)
+ {
+ shape_area+= prev_x*first_y - prev_y*first_x;
+ if (fabs(shape_area) < 1e-8)
+ {
+ buffer.length(shape_pos);
+ GCALC_DBUG_RETURN(0);
+ }
+ }
+
+ if ((cur_shape == Gcalc_function::shape_polygon ||
+ cur_shape == Gcalc_function::shape_hole) &&
+ prev_x == first_x && prev_y == first_y)
+ {
+ n_points--;
+ buffer.write_at_position(shape_pos+4, n_points);
+ goto do_complete;
+ }
+ buffer.write_at_position(shape_pos+4, n_points);
+ }
+
+ if (buffer.reserve(8*2, 512))
+ GCALC_DBUG_RETURN(1);
+ buffer.q_append(prev_x);
+ buffer.q_append(prev_y);
+
+do_complete:
+ buffer.write_at_position(shape_pos, (uint32) cur_shape);
+
+ if (!n_shapes++)
+ {
+ GCALC_DBUG_ASSERT(cur_shape != Gcalc_function::shape_hole);
+ common_shapetype= cur_shape;
+ }
+ else if (cur_shape == Gcalc_function::shape_hole)
+ {
+ ++n_holes;
+ }
+ else if (!collection_result && (cur_shape != common_shapetype))
+ {
+ collection_result= true;
+ }
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_result_receiver::single_point(double x, double y)
+{
+ return start_shape(Gcalc_function::shape_point) ||
+ add_point(x, y) ||
+ complete_shape();
+}
+
+
+int Gcalc_result_receiver::done()
+{
+ return 0;
+}
+
+
+void Gcalc_result_receiver::reset()
+{
+ buffer.length(0);
+ collection_result= FALSE;
+ n_shapes= n_holes= 0;
+}
+
+
+int Gcalc_result_receiver::get_result_typeid()
+{
+ if (!n_shapes || collection_result)
+ return Geometry::wkb_geometrycollection;
+
+ switch (common_shapetype)
+ {
+ case Gcalc_function::shape_polygon:
+ return (n_shapes - n_holes == 1) ?
+ Geometry::wkb_polygon : Geometry::wkb_multipolygon;
+ case Gcalc_function::shape_point:
+ return (n_shapes == 1) ? Geometry::wkb_point : Geometry::wkb_multipoint;
+ case Gcalc_function::shape_line:
+ return (n_shapes == 1) ? Geometry::wkb_linestring :
+ Geometry::wkb_multilinestring;
+ default:
+ GCALC_DBUG_ASSERT(0);
+ }
+ return 0;
+}
+
+
+int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_position,
+ uint32 *position_shift)
+{
+ char *ptr;
+ int source_len;
+ GCALC_DBUG_ENTER("Gcalc_result_receiver::move_hole");
+ GCALC_DBUG_PRINT(("ps %d %d", dest_position, source_position));
+
+ *position_shift= source_len= buffer.length() - source_position;
+
+ if (dest_position == source_position)
+ GCALC_DBUG_RETURN(0);
+
+ if (buffer.reserve(source_len, MY_ALIGN(source_len, 512)))
+ GCALC_DBUG_RETURN(1);
+
+ ptr= (char *) buffer.ptr();
+ memmove(ptr + dest_position + source_len, ptr + dest_position,
+ buffer.length() - dest_position);
+ memcpy(ptr + dest_position, ptr + buffer.length(), source_len);
+ GCALC_DBUG_RETURN(0);
+}
+
+
+Gcalc_operation_reducer::Gcalc_operation_reducer(size_t blk_size) :
+ Gcalc_dyn_list(blk_size, sizeof(res_point)),
+#ifndef GCALC_DBUG_OFF
+ n_res_points(0),
+#endif /*GCALC_DBUG_OFF*/
+ m_res_hook((Gcalc_dyn_list::Item **)&m_result),
+ m_first_active_thread(NULL)
+{}
+
+
+void Gcalc_operation_reducer::init(Gcalc_function *fn, modes mode)
+{
+ m_fn= fn;
+ m_mode= mode;
+ m_first_active_thread= NULL;
+ m_lines= NULL;
+ m_lines_hook= (Gcalc_dyn_list::Item **) &m_lines;
+ m_poly_borders= NULL;
+ m_poly_borders_hook= (Gcalc_dyn_list::Item **) &m_poly_borders;
+ GCALC_SET_TERMINATED(killed, 0);
+}
+
+
+Gcalc_operation_reducer::
+Gcalc_operation_reducer(Gcalc_function *fn, modes mode, size_t blk_size) :
+ Gcalc_dyn_list(blk_size, sizeof(res_point)),
+ m_res_hook((Gcalc_dyn_list::Item **)&m_result)
+{
+ init(fn, mode);
+}
+
+
+#ifdef TMP_BLOCK
+void Gcalc_operation_reducer::res_point::set(const Gcalc_scan_iterator *si)
+{
+ if ((intersection_point= si->intersection_step()))
+ ii= si->get_cur_ii();
+ else
+ pi= si->get_cur_pi();
+}
+#endif /*TMP_BLOCK*/
+void Gcalc_operation_reducer::res_point::set(const Gcalc_scan_iterator *si)
+{
+ intersection_point= si->intersection_step();
+ pi= si->get_cur_pi();
+}
+
+
+Gcalc_operation_reducer::res_point *
+ Gcalc_operation_reducer::add_res_point(Gcalc_function::shape_type type)
+{
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::add_res_point");
+ res_point *result= (res_point *)new_item();
+ *m_res_hook= result;
+ result->prev_hook= m_res_hook;
+ m_res_hook= &result->next;
+ result->type= type;
+#ifndef GCALC_DBUG_OFF
+ result->point_n= n_res_points++;
+#endif /*GCALC_DBUG_OFF*/
+ GCALC_DBUG_RETURN(result);
+}
+
+int Gcalc_operation_reducer::add_line(int incoming, active_thread *t,
+ const Gcalc_scan_iterator::point *p)
+{
+ line *l= new_line();
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::add_line");
+ if (!l)
+ GCALC_DBUG_RETURN(1);
+ l->incoming= incoming;
+ l->t= t;
+ l->p= p;
+ *m_lines_hook= l;
+ m_lines_hook= &l->next;
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_reducer::add_poly_border(int incoming,
+ active_thread *t, int prev_state, const Gcalc_scan_iterator::point *p)
+{
+ poly_border *b= new_poly_border();
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::add_poly_border");
+ if (!b)
+ GCALC_DBUG_RETURN(1);
+ b->incoming= incoming;
+ b->t= t;
+ b->prev_state= prev_state;
+ b->p= p;
+ *m_poly_borders_hook= b;
+ m_poly_borders_hook= &b->next;
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_reducer::continue_range(active_thread *t,
+ const Gcalc_heap::Info *p,
+ const Gcalc_heap::Info *p_next)
+{
+ res_point *rp= add_res_point(t->rp->type);
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::continue_range");
+ if (!rp)
+ GCALC_DBUG_RETURN(1);
+ rp->glue= NULL;
+ rp->down= t->rp;
+ t->rp->up= rp;
+ rp->intersection_point= false;
+ rp->pi= p;
+ t->rp= rp;
+ t->p1= p;
+ t->p2= p_next;
+ GCALC_DBUG_RETURN(0);
+}
+
+
+inline int Gcalc_operation_reducer::continue_i_range(active_thread *t,
+ const Gcalc_heap::Info *ii)
+{
+ res_point *rp= add_res_point(t->rp->type);
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::continue_i_range");
+ if (!rp)
+ GCALC_DBUG_RETURN(1);
+ rp->glue= NULL;
+ rp->down= t->rp;
+ t->rp->up= rp;
+ rp->intersection_point= true;
+ rp->pi= ii;
+ t->rp= rp;
+ GCALC_DBUG_RETURN(0);
+}
+
+int Gcalc_operation_reducer::end_couple(active_thread *t0, active_thread *t1,
+ const Gcalc_heap::Info *p)
+{
+ res_point *rp0, *rp1;
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::end_couple");
+ GCALC_DBUG_ASSERT(t0->rp->type == t1->rp->type);
+ if (!(rp0= add_res_point(t0->rp->type)) ||
+ !(rp1= add_res_point(t0->rp->type)))
+ GCALC_DBUG_RETURN(1);
+ rp0->down= t0->rp;
+ rp1->down= t1->rp;
+ rp1->glue= rp0;
+ rp0->glue= rp1;
+ rp0->up= rp1->up= NULL;
+ t0->rp->up= rp0;
+ t1->rp->up= rp1;
+ rp0->intersection_point= rp1->intersection_point= false;
+ rp0->pi= rp1->pi= p;
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_reducer::count_slice(Gcalc_scan_iterator *si)
+{
+ Gcalc_point_iterator pi(si);
+ int prev_state= 0;
+ int sav_prev_state;
+ active_thread *prev_range= NULL;
+ const Gcalc_scan_iterator::event_point *events;
+ const Gcalc_scan_iterator::point *eq_start;
+ active_thread **cur_t_hook= &m_first_active_thread;
+ active_thread **starting_t_hook;
+ active_thread *bottom_threads= NULL;
+ active_thread *eq_thread, *point_thread;;
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::count_slice");
+
+ m_fn->clear_i_states();
+ /* Walk to the event, remembering what is needed. */
+ for (; pi.point() != si->get_event_position();
+ ++pi, cur_t_hook= (active_thread **) &(*cur_t_hook)->next)
+ {
+ active_thread *cur_t= *cur_t_hook;
+ if (cur_t->enabled() &&
+ cur_t->rp->type == Gcalc_function::shape_polygon)
+ {
+ prev_state^= 1;
+ prev_range= prev_state ? cur_t : 0;
+ }
+ if (m_fn->get_shape_kind(pi.get_shape()) == Gcalc_function::shape_polygon)
+ m_fn->invert_i_state(pi.get_shape());
+ }
+
+ events= si->get_events();
+ if (events->simple_event())
+ {
+ active_thread *cur_t= *cur_t_hook;
+ switch (events->event)
+ {
+ case scev_point:
+ {
+ if (cur_t->enabled() &&
+ continue_range(cur_t, events->pi, events->next_pi))
+ GCALC_DBUG_RETURN(1);
+ break;
+ }
+ case scev_end:
+ {
+ if (cur_t->enabled() && end_line(cur_t, si))
+ GCALC_DBUG_RETURN(1);
+ *cur_t_hook= cur_t->get_next();
+ free_item(cur_t);
+ break;
+ }
+ case scev_two_ends:
+ {
+ if (cur_t->enabled() && cur_t->get_next()->enabled())
+ {
+ /* When two threads are ended here */
+ if (end_couple(cur_t, cur_t->get_next(), events->pi))
+ GCALC_DBUG_RETURN(1);
+ }
+ else if (cur_t->enabled() || cur_t->get_next()->enabled())
+ {
+ /* Rare case when edges of a polygon coincide */
+ if (end_line(cur_t->enabled() ? cur_t : cur_t->get_next(), si))
+ GCALC_DBUG_RETURN(1);
+ }
+ *cur_t_hook= cur_t->get_next()->get_next();
+ free_item(cur_t->next);
+ free_item(cur_t);
+ break;
+ }
+ default:
+ GCALC_DBUG_ASSERT(0);
+ }
+ GCALC_DBUG_RETURN(0);
+ }
+
+ starting_t_hook= cur_t_hook;
+ sav_prev_state= prev_state;
+
+ /* Walk through the event, collecting all the 'incoming' threads */
+ for (; events; events= events->get_next())
+ {
+ active_thread *cur_t= *cur_t_hook;
+
+ if (events->event == scev_single_point)
+ continue;
+
+ if (events->event == scev_thread ||
+ events->event == scev_two_threads)
+ {
+ active_thread *new_t= new_active_thread();
+ if (!new_t)
+ GCALC_DBUG_RETURN(1);
+ new_t->rp= NULL;
+ /* Insert into the main thread list before the current */
+ new_t->next= cur_t;
+ *cur_t_hook= new_t;
+ cur_t_hook= (active_thread **) &new_t->next;
+ }
+ else
+ {
+ if (events->is_bottom())
+ {
+ /* Move thread from the main list to the bottom_threads. */
+ *cur_t_hook= cur_t->get_next();
+ cur_t->next= bottom_threads;
+ bottom_threads= cur_t;
+ }
+ if (cur_t->enabled())
+ {
+ if (cur_t->rp->type == Gcalc_function::shape_line)
+ {
+ GCALC_DBUG_ASSERT(!prev_state);
+ add_line(1, cur_t, events);
+ }
+ else
+ {
+ add_poly_border(1, cur_t, prev_state, events);
+ prev_state^= 1;
+ }
+ if (!events->is_bottom())
+ {
+ active_thread *new_t= new_active_thread();
+ if (!new_t)
+ GCALC_DBUG_RETURN(1);
+ new_t->rp= NULL;
+ /* Replace the current thread with the new. */
+ new_t->next= cur_t->next;
+ *cur_t_hook= new_t;
+ cur_t_hook= (active_thread **) &new_t->next;
+ /* And move old to the bottom list */
+ cur_t->next= bottom_threads;
+ bottom_threads= cur_t;
+ }
+ }
+ else if (!events->is_bottom())
+ cur_t_hook= (active_thread **) &cur_t->next;
+ }
+ }
+ prev_state= sav_prev_state;
+ cur_t_hook= starting_t_hook;
+
+ eq_start= pi.point();
+ eq_thread= point_thread= *starting_t_hook;
+ m_fn->clear_b_states();
+ while (eq_start != si->get_event_end())
+ {
+ const Gcalc_scan_iterator::point *cur_eq;
+ int in_state, after_state;
+
+ ++pi;
+ point_thread= point_thread->get_next();
+
+ if (pi.point() != si->get_event_end() &&
+ eq_start->cmp_dx_dy(pi.point()) == 0)
+ continue;
+
+ for (cur_eq= eq_start; cur_eq != pi.point(); cur_eq= cur_eq->get_next())
+ m_fn->set_b_state(cur_eq->get_shape());
+ in_state= m_fn->count();
+
+ m_fn->clear_b_states();
+ for (cur_eq= eq_start; cur_eq != pi.point(); cur_eq= cur_eq->get_next())
+ {
+ gcalc_shape_info si= cur_eq->get_shape();
+ if ((m_fn->get_shape_kind(si) == Gcalc_function::shape_polygon))
+ m_fn->invert_i_state(si);
+ }
+ after_state= m_fn->count();
+ if (prev_state != after_state)
+ {
+ if (add_poly_border(0, eq_thread, prev_state, eq_start))
+ GCALC_DBUG_RETURN(1);
+ }
+ else if (!prev_state /* &&!after_state */ && in_state)
+ {
+ if (add_line(0, eq_thread, eq_start))
+ GCALC_DBUG_RETURN(1);
+ }
+
+ prev_state= after_state;
+ eq_start= pi.point();
+ eq_thread= point_thread;
+ }
+
+ if (!sav_prev_state && !m_poly_borders && !m_lines)
+ {
+ /* Check if we need to add the event point itself */
+ m_fn->clear_i_states();
+ /* b_states supposed to be clean already */
+ for (pi.restart(si); pi.point() != si->get_event_position(); ++pi)
+ {
+ if (m_fn->get_shape_kind(pi.get_shape()) == Gcalc_function::shape_polygon)
+ m_fn->invert_i_state(pi.get_shape());
+ }
+ for (events= si->get_events(); events; events= events->get_next())
+ m_fn->set_b_state(events->get_shape());
+
+ GCALC_DBUG_RETURN(m_fn->count() ? add_single_point(si) : 0);
+ }
+
+ if (m_poly_borders)
+ {
+ *m_poly_borders_hook= NULL;
+ while (m_poly_borders)
+ {
+ poly_border *pb1, *pb2;
+ pb1= m_poly_borders;
+ GCALC_DBUG_ASSERT(m_poly_borders->next);
+
+ pb2= get_pair_border(pb1);
+ /* Remove pb1 from the list. The pb2 already removed in get_pair_border. */
+ m_poly_borders= pb1->get_next();
+ if (connect_threads(pb1->incoming, pb2->incoming,
+ pb1->t, pb2->t, pb1->p, pb2->p,
+ prev_range, si, Gcalc_function::shape_polygon))
+ GCALC_DBUG_RETURN(1);
+
+ free_item(pb1);
+ free_item(pb2);
+ }
+ m_poly_borders_hook= (Gcalc_dyn_list::Item **) &m_poly_borders;
+ m_poly_borders= NULL;
+ }
+
+ if (m_lines)
+ {
+ *m_lines_hook= NULL;
+ if (m_lines->get_next() &&
+ !m_lines->get_next()->get_next())
+ {
+ if (connect_threads(m_lines->incoming, m_lines->get_next()->incoming,
+ m_lines->t, m_lines->get_next()->t,
+ m_lines->p, m_lines->get_next()->p,
+ NULL, si, Gcalc_function::shape_line))
+ GCALC_DBUG_RETURN(1);
+ }
+ else
+ {
+ for (line *cur_line= m_lines; cur_line; cur_line= cur_line->get_next())
+ {
+ if (cur_line->incoming)
+ {
+ if (end_line(cur_line->t, si))
+ GCALC_DBUG_RETURN(1);
+ }
+ else
+ start_line(cur_line->t, cur_line->p, si);
+ }
+ }
+ free_list(m_lines);
+ m_lines= NULL;
+ m_lines_hook= (Gcalc_dyn_list::Item **) &m_lines;
+ }
+
+ if (bottom_threads)
+ free_list(bottom_threads);
+
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_reducer::add_single_point(const Gcalc_scan_iterator *si)
+{
+ res_point *rp= add_res_point(Gcalc_function::shape_point);
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::add_single_point");
+ if (!rp)
+ GCALC_DBUG_RETURN(1);
+ rp->glue= rp->up= rp->down= NULL;
+ rp->set(si);
+ GCALC_DBUG_RETURN(0);
+}
+
+
+Gcalc_operation_reducer::poly_border
+ *Gcalc_operation_reducer::get_pair_border(poly_border *b1)
+{
+ poly_border *prev_b= b1;
+ poly_border *result= b1->get_next();
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::get_pair_border");
+ if (b1->prev_state)
+ {
+ if (b1->incoming)
+ {
+ /* Find the first outgoing, otherwise the last one. */
+ while (result->incoming && result->get_next())
+ {
+ prev_b= result;
+ result= result->get_next();
+ }
+ }
+ else
+ {
+ /* Get the last one */
+ while (result->get_next())
+ {
+ prev_b= result;
+ result= result->get_next();
+ }
+ }
+ }
+ else /* !b1->prev_state */
+ {
+ if (b1->incoming)
+ {
+ /* Get the next incoming, otherwise the last one. */
+ while (!result->incoming && result->get_next())
+ {
+ prev_b= result;
+ result= result->get_next();
+ }
+ }
+ else
+ {
+ /* Just pick the next one */
+ }
+ }
+ /* Delete the result from the list. */
+ prev_b->next= result->next;
+ GCALC_DBUG_RETURN(result);
+}
+
+
+int Gcalc_operation_reducer::connect_threads(
+ int incoming_a, int incoming_b,
+ active_thread *ta, active_thread *tb,
+ const Gcalc_scan_iterator::point *pa, const Gcalc_scan_iterator::point *pb,
+ active_thread *prev_range,
+ const Gcalc_scan_iterator *si, Gcalc_function::shape_type s_t)
+{
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::connect_threads");
+ GCALC_DBUG_PRINT(("incoming %d %d", incoming_a, incoming_b));
+ if (incoming_a && incoming_b)
+ {
+ res_point *rpa, *rpb;
+ GCALC_DBUG_ASSERT(ta->rp->type == tb->rp->type);
+ if (!(rpa= add_res_point(ta->rp->type)) ||
+ !(rpb= add_res_point(ta->rp->type)))
+ GCALC_DBUG_RETURN(1);
+ rpa->down= ta->rp;
+ rpb->down= tb->rp;
+ rpb->glue= rpa;
+ rpa->glue= rpb;
+ rpa->up= rpb->up= NULL;
+ ta->rp->up= rpa;
+ tb->rp->up= rpb;
+ rpa->set(si);
+ rpb->set(si);
+ ta->rp= tb->rp= NULL;
+ GCALC_DBUG_RETURN(0);
+ }
+ if (!incoming_a)
+ {
+ GCALC_DBUG_ASSERT(!incoming_b);
+
+ res_point *rp0, *rp1;
+ if (!(rp0= add_res_point(s_t)) || !(rp1= add_res_point(s_t)))
+ GCALC_DBUG_RETURN(1);
+ rp0->glue= rp1;
+ rp1->glue= rp0;
+ rp0->set(si);
+ rp1->set(si);
+ rp0->down= rp1->down= NULL;
+ ta->rp= rp0;
+ tb->rp= rp1;
+ ta->p1= pa->pi;
+ ta->p2= pa->next_pi;
+
+ tb->p1= pb->pi;
+ tb->p2= pb->next_pi;
+
+ if (prev_range)
+ {
+ rp0->outer_poly= prev_range->thread_start;
+ tb->thread_start= prev_range->thread_start;
+ /* Chack if needed */
+ ta->thread_start= prev_range->thread_start;
+ }
+ else
+ {
+ rp0->outer_poly= 0;
+ ta->thread_start= rp0;
+ /* Chack if needed */
+ tb->thread_start= rp0;
+ }
+ GCALC_DBUG_RETURN(0);
+ }
+ /* else, if only ta is incoming */
+
+ GCALC_DBUG_ASSERT(tb != ta);
+ tb->rp= ta->rp;
+ tb->thread_start= ta->thread_start;
+ if (Gcalc_scan_iterator::point::
+ cmp_dx_dy(ta->p1, ta->p2, pb->pi, pb->next_pi) != 0)
+ {
+ if (si->intersection_step() ?
+ continue_i_range(tb, si->get_cur_pi()) :
+ continue_range(tb, si->get_cur_pi(), pb->next_pi))
+ GCALC_DBUG_RETURN(1);
+ }
+ tb->p1= pb->pi;
+ tb->p2= pb->next_pi;
+
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_reducer::start_line(active_thread *t,
+ const Gcalc_scan_iterator::point *p,
+ const Gcalc_scan_iterator *si)
+{
+ res_point *rp= add_res_point(Gcalc_function::shape_line);
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::start_line");
+ if (!rp)
+ GCALC_DBUG_RETURN(1);
+ rp->glue= rp->down= NULL;
+ rp->set(si);
+ t->rp= rp;
+ t->p1= p->pi;
+ t->p2= p->next_pi;
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_reducer::end_line(active_thread *t,
+ const Gcalc_scan_iterator *si)
+{
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::end_line");
+ GCALC_DBUG_ASSERT(t->rp->type == Gcalc_function::shape_line);
+ res_point *rp= add_res_point(Gcalc_function::shape_line);
+ if (!rp)
+ GCALC_DBUG_RETURN(1);
+ rp->glue= rp->up= NULL;
+ rp->down= t->rp;
+ rp->set(si);
+ t->rp->up= rp;
+ t->rp= NULL;
+
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_reducer::count_all(Gcalc_heap *hp)
+{
+ Gcalc_scan_iterator si;
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::count_all");
+ si.init(hp);
+ GCALC_SET_TERMINATED(si.killed, killed);
+ while (si.more_points())
+ {
+ if (si.step())
+ GCALC_DBUG_RETURN(1);
+ if (count_slice(&si))
+ GCALC_DBUG_RETURN(1);
+ }
+ GCALC_DBUG_RETURN(0);
+}
+
+inline void Gcalc_operation_reducer::free_result(res_point *res)
+{
+ if ((*res->prev_hook= res->next))
+ {
+ res->get_next()->prev_hook= res->prev_hook;
+ }
+ free_item(res);
+}
+
+
+inline int Gcalc_operation_reducer::get_single_result(res_point *res,
+ Gcalc_result_receiver *storage)
+{
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::get_single_result");
+ if (res->intersection_point)
+ {
+ double x, y;
+ res->pi->calc_xy(&x, &y);
+ if (storage->single_point(x,y))
+ GCALC_DBUG_RETURN(1);
+ }
+ else
+ if (storage->single_point(res->pi->x, res->pi->y))
+ GCALC_DBUG_RETURN(1);
+ free_result(res);
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_reducer::get_result_thread(res_point *cur,
+ Gcalc_result_receiver *storage,
+ int move_upward,
+ res_point *first_poly_node)
+{
+ res_point *next;
+ bool glue_step= false;
+ double x, y;
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::get_result_thread");
+ while (cur)
+ {
+ if (!glue_step)
+ {
+ if (cur->intersection_point)
+ {
+ cur->pi->calc_xy(&x, &y);
+ }
+ else
+ {
+ x= cur->pi->x;
+ y= cur->pi->y;
+ }
+ if (storage->add_point(x, y))
+ GCALC_DBUG_RETURN(1);
+ }
+
+ next= move_upward ? cur->up : cur->down;
+ if (!next && !glue_step)
+ {
+ next= cur->glue;
+ move_upward^= 1;
+ glue_step= true;
+ if (next)
+ next->glue= NULL;
+ }
+ else
+ glue_step= false;
+
+ cur->first_poly_node= first_poly_node;
+ free_result(cur);
+ cur= next;
+ }
+ GCALC_DBUG_RETURN(0);
+}
+
+
+int Gcalc_operation_reducer::get_polygon_result(res_point *cur,
+ Gcalc_result_receiver *storage,
+ res_point *first_poly_node)
+{
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::get_polygon_result");
+ res_point *glue= cur->glue;
+ glue->up->down= NULL;
+ free_result(glue);
+ GCALC_DBUG_RETURN(get_result_thread(cur, storage, 1, first_poly_node) ||
+ storage->complete_shape());
+}
+
+
+int Gcalc_operation_reducer::get_line_result(res_point *cur,
+ Gcalc_result_receiver *storage)
+{
+ res_point *next;
+ res_point *cur_orig= cur;
+ int move_upward= 1;
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::get_line_result");
+ if (cur->glue)
+ {
+ /* Here we have to find the beginning of the line */
+ next= cur->up;
+ move_upward= 1;
+ while (next)
+ {
+ cur= next;
+ next= move_upward ? next->up : next->down;
+ if (!next)
+ {
+ next= cur->glue;
+ if (next == cur_orig)
+ {
+ /* It's the line loop */
+ cur= cur_orig;
+ cur->glue->glue= NULL;
+ move_upward= 1;
+ break;
+ }
+ move_upward^= 1;
+ }
+ }
+ }
+
+ GCALC_DBUG_RETURN(get_result_thread(cur, storage, move_upward, 0) ||
+ storage->complete_shape());
+}
+
+
+int Gcalc_operation_reducer::get_result(Gcalc_result_receiver *storage)
+{
+ poly_instance *polygons= NULL;
+
+ GCALC_DBUG_ENTER("Gcalc_operation_reducer::get_result");
+ *m_res_hook= NULL;
+
+ while (m_result)
+ {
+ Gcalc_function::shape_type shape= m_result->type;
+ if (shape == Gcalc_function::shape_point)
+ {
+ if (get_single_result(m_result, storage))
+ GCALC_DBUG_RETURN(1);
+ continue;
+ }
+ if (shape == Gcalc_function::shape_polygon)
+ {
+ if (m_result->outer_poly)
+ {
+ uint32 insert_position, hole_position, position_shift;
+ poly_instance *cur_poly;
+ insert_position= m_result->outer_poly->first_poly_node->poly_position;
+ GCALC_DBUG_ASSERT(insert_position);
+ hole_position= storage->position();
+ storage->start_shape(Gcalc_function::shape_hole);
+ if (get_polygon_result(m_result, storage,
+ m_result->outer_poly->first_poly_node) ||
+ storage->move_hole(insert_position, hole_position,
+ &position_shift))
+ GCALC_DBUG_RETURN(1);
+ for (cur_poly= polygons;
+ cur_poly && *cur_poly->after_poly_position >= insert_position;
+ cur_poly= cur_poly->get_next())
+ *cur_poly->after_poly_position+= position_shift;
+ }
+ else
+ {
+ uint32 *poly_position= &m_result->poly_position;
+ poly_instance *p= new_poly();
+ p->after_poly_position= poly_position;
+ p->next= polygons;
+ polygons= p;
+ storage->start_shape(Gcalc_function::shape_polygon);
+ if (get_polygon_result(m_result, storage, m_result))
+ GCALC_DBUG_RETURN(1);
+ *poly_position= storage->position();
+ }
+ }
+ else
+ {
+ storage->start_shape(shape);
+ if (get_line_result(m_result, storage))
+ GCALC_DBUG_RETURN(1);
+ }
+ }
+
+ m_res_hook= (Gcalc_dyn_list::Item **)&m_result;
+ storage->done();
+ GCALC_DBUG_RETURN(0);
+}
+
+
+void Gcalc_operation_reducer::reset()
+{
+ free_list((Gcalc_heap::Item **) &m_result, m_res_hook);
+ m_res_hook= (Gcalc_dyn_list::Item **)&m_result;
+ free_list(m_first_active_thread);
+}
+
+#endif /*HAVE_SPATIAL*/
+
diff --git a/sql/gcalc_tools.h b/sql/gcalc_tools.h
new file mode 100644
index 00000000000..12ee56732a2
--- /dev/null
+++ b/sql/gcalc_tools.h
@@ -0,0 +1,348 @@
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+ Copyright (C) 2011 Monty Program Ab.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#ifndef GCALC_TOOLS_INCLUDED
+#define GCALC_TOOLS_INCLUDED
+
+#include "gcalc_slicescan.h"
+#include "sql_string.h"
+
+
+/*
+ The Gcalc_function class objects are used to check for a binary relation.
+ The relation can be constructed with the prefix notation using predicates as
+ op_not (as !A)
+ op_union ( A || B || C... )
+ op_intersection ( A && B && C ... )
+ op_symdifference ( A+B+C+... == 1 )
+ op_difference ( A && !(B||C||..))
+ with the calls of the add_operation(operation, n_operands) method.
+ The relation is calculated over a set of shapes, that in turn have
+ to be added with the add_new_shape() method. All the 'shapes' can
+ be set to 0 with clear_shapes() method and single value
+ can be changed with the invert_state() method.
+ Then the value of the relation can be calculated with the count() method.
+ Frequently used method is find_function(Gcalc_scan_iterator it) that
+ iterates through the 'it' until the relation becomes TRUE.
+*/
+
+class Gcalc_function
+{
+private:
+ String shapes_buffer;
+ String function_buffer;
+ int *i_states;
+ int *b_states;
+ uint32 cur_object_id;
+ uint n_shapes;
+ int count_internal(const char *cur_func, uint set_type,
+ const char **end);
+public:
+ enum value
+ {
+ v_empty= 0x0000000,
+ v_find_t= 0x1000000,
+ v_find_f= 0x2000000,
+ v_t_found= 0x3000000,
+ v_f_found= 0x4000000,
+ v_mask= 0x7000000
+ };
+ enum op_type
+ {
+ op_not= 0x80000000,
+ op_shape= 0x00000000,
+ op_union= 0x10000000,
+ op_intersection= 0x20000000,
+ op_symdifference= 0x30000000,
+ op_difference= 0x40000000,
+ op_repeat= 0x50000000,
+ op_border= 0x60000000,
+ op_internals= 0x70000000,
+ op_false= 0x08000000,
+ op_any= 0x78000000 /* The mask to get any of the operations */
+ };
+ enum shape_type
+ {
+ shape_point= 0,
+ shape_line= 1,
+ shape_polygon= 2,
+ shape_hole= 3
+ };
+ Gcalc_function() : n_shapes(0) {}
+ gcalc_shape_info add_new_shape(uint32 shape_id, shape_type shape_kind);
+ /*
+ Adds the leaf operation that returns the shape value.
+ Also adds the shape to the list of operands.
+ */
+ int single_shape_op(shape_type shape_kind, gcalc_shape_info *si);
+ void add_operation(uint operation, uint32 n_operands);
+ void add_not_operation(op_type operation, uint32 n_operands);
+ uint32 get_next_expression_pos() { return function_buffer.length(); }
+ void add_operands_to_op(uint32 operation_pos, uint32 n_operands);
+ int repeat_expression(uint32 exp_pos);
+ void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; }
+ int reserve_shape_buffer(uint n_shapes);
+ int reserve_op_buffer(uint n_ops);
+ uint get_nshapes() const { return n_shapes; }
+ shape_type get_shape_kind(gcalc_shape_info si) const
+ {
+ return (shape_type) uint4korr(shapes_buffer.ptr() + (si*4));
+ }
+
+ void set_states(int *shape_states) { i_states= shape_states; }
+ int alloc_states();
+ void invert_i_state(gcalc_shape_info shape) { i_states[shape]^= 1; }
+ void set_i_state(gcalc_shape_info shape) { i_states[shape]= 1; }
+ void clear_i_state(gcalc_shape_info shape) { i_states[shape]= 0; }
+ void set_b_state(gcalc_shape_info shape) { b_states[shape]= 1; }
+ void clear_b_state(gcalc_shape_info shape) { b_states[shape]= 0; }
+ int get_state(gcalc_shape_info shape)
+ { return i_states[shape] | b_states[shape]; }
+ int get_i_state(gcalc_shape_info shape) { return i_states[shape]; }
+ int get_b_state(gcalc_shape_info shape) { return b_states[shape]; }
+ int count()
+ { return count_internal(function_buffer.ptr(), 0, 0); }
+ void clear_i_states();
+ void clear_b_states();
+ void reset();
+
+ int check_function(Gcalc_scan_iterator &scan_it);
+};
+
+
+/*
+ Gcalc_operation_transporter class extends the Gcalc_shape_transporter.
+ In addition to the parent's functionality, it fills the Gcalc_function
+ object so it has the function that determines the proper shape.
+ For example Multipolyline will be represented as an union of polylines.
+*/
+
+class Gcalc_operation_transporter : public Gcalc_shape_transporter
+{
+protected:
+ Gcalc_function *m_fn;
+ gcalc_shape_info m_si;
+public:
+ Gcalc_operation_transporter(Gcalc_function *fn, Gcalc_heap *heap) :
+ Gcalc_shape_transporter(heap), m_fn(fn) {}
+
+ int single_point(double x, double y);
+ int start_line();
+ int complete_line();
+ int start_poly();
+ int complete_poly();
+ int start_ring();
+ int complete_ring();
+ int add_point(double x, double y);
+ int start_collection(int n_objects);
+ int empty_shape();
+};
+
+
+/*
+ When we calculate the result of an spatial operation like
+ Union or Intersection, we receive vertexes of the result
+ one-by-one, and probably need to treat them in variative ways.
+ So, the Gcalc_result_receiver class designed to get these
+ vertexes and construct shapes/objects out of them.
+ and to store the result in an appropriate format
+*/
+
+class Gcalc_result_receiver
+{
+ String buffer;
+ uint32 n_points;
+ Gcalc_function::shape_type common_shapetype;
+ bool collection_result;
+ uint32 n_shapes;
+ uint32 n_holes;
+
+ Gcalc_function::shape_type cur_shape;
+ uint32 shape_pos;
+ double first_x, first_y, prev_x, prev_y;
+ double shape_area;
+public:
+ Gcalc_result_receiver() : collection_result(FALSE), n_shapes(0), n_holes(0)
+ {}
+ int start_shape(Gcalc_function::shape_type shape);
+ int add_point(double x, double y);
+ int complete_shape();
+ int single_point(double x, double y);
+ int done();
+ void reset();
+
+ const char *result() { return buffer.ptr(); }
+ uint length() { return buffer.length(); }
+ int get_nshapes() { return n_shapes; }
+ int get_nholes() { return n_holes; }
+ int get_result_typeid();
+ uint32 position() { return buffer.length(); }
+ int move_hole(uint32 dest_position, uint32 source_position,
+ uint32 *position_shift);
+};
+
+
+/*
+ Gcalc_operation_reducer class incapsulates the spatial
+ operation functionality. It analyses the slices generated by
+ the slicescan and calculates the shape of the result defined
+ by some Gcalc_function.
+*/
+
+class Gcalc_operation_reducer : public Gcalc_dyn_list
+{
+public:
+ enum modes
+ {
+ /* Numeric values important here - careful with changing */
+ default_mode= 0,
+ prefer_big_with_holes= 1,
+ polygon_selfintersections_allowed= 2, /* allowed in the result */
+ line_selfintersections_allowed= 4 /* allowed in the result */
+ };
+
+ Gcalc_operation_reducer(size_t blk_size=8192);
+ void init(Gcalc_function *fn, modes mode= default_mode);
+ Gcalc_operation_reducer(Gcalc_function *fn, modes mode= default_mode,
+ size_t blk_size=8192);
+ GCALC_DECL_TERMINATED_STATE(killed)
+ int count_slice(Gcalc_scan_iterator *si);
+ int count_all(Gcalc_heap *hp);
+ int get_result(Gcalc_result_receiver *storage);
+ void reset();
+
+#ifndef GCALC_DBUG_OFF
+ int n_res_points;
+#endif /*GCALC_DBUG_OFF*/
+ class res_point : public Gcalc_dyn_list::Item
+ {
+ public:
+ int intersection_point;
+ union
+ {
+ const Gcalc_heap::Info *pi;
+ res_point *first_poly_node;
+ };
+ union
+ {
+ res_point *outer_poly;
+ uint32 poly_position;
+ };
+ res_point *up;
+ res_point *down;
+ res_point *glue;
+ Gcalc_function::shape_type type;
+ Gcalc_dyn_list::Item **prev_hook;
+#ifndef GCALC_DBUG_OFF
+ int point_n;
+#endif /*GCALC_DBUG_OFF*/
+ void set(const Gcalc_scan_iterator *si);
+ res_point *get_next() { return (res_point *)next; }
+ };
+
+ class active_thread : public Gcalc_dyn_list::Item
+ {
+ public:
+ res_point *rp;
+ res_point *thread_start;
+
+ const Gcalc_heap::Info *p1, *p2;
+ res_point *enabled() { return rp; }
+ active_thread *get_next() { return (active_thread *)next; }
+ };
+
+ class poly_instance : public Gcalc_dyn_list::Item
+ {
+ public:
+ uint32 *after_poly_position;
+ poly_instance *get_next() { return (poly_instance *)next; }
+ };
+
+ class line : public Gcalc_dyn_list::Item
+ {
+ public:
+ active_thread *t;
+ int incoming;
+ const Gcalc_scan_iterator::point *p;
+ line *get_next() { return (line *)next; }
+ };
+
+ class poly_border : public Gcalc_dyn_list::Item
+ {
+ public:
+ active_thread *t;
+ int incoming;
+ int prev_state;
+ const Gcalc_scan_iterator::point *p;
+ poly_border *get_next() { return (poly_border *)next; }
+ };
+
+ line *m_lines;
+ Gcalc_dyn_list::Item **m_lines_hook;
+ poly_border *m_poly_borders;
+ Gcalc_dyn_list::Item **m_poly_borders_hook;
+ line *new_line() { return (line *) new_item(); }
+ poly_border *new_poly_border() { return (poly_border *) new_item(); }
+ int add_line(int incoming, active_thread *t,
+ const Gcalc_scan_iterator::point *p);
+ int add_poly_border(int incoming, active_thread *t, int prev_state,
+ const Gcalc_scan_iterator::point *p);
+
+protected:
+ Gcalc_function *m_fn;
+ Gcalc_dyn_list::Item **m_res_hook;
+ res_point *m_result;
+ int m_mode;
+
+ res_point *result_heap;
+ active_thread *m_first_active_thread;
+
+ res_point *add_res_point(Gcalc_function::shape_type type);
+ active_thread *new_active_thread() { return (active_thread *)new_item(); }
+
+ poly_instance *new_poly() { return (poly_instance *) new_item(); }
+
+private:
+ int start_line(active_thread *t, const Gcalc_scan_iterator::point *p,
+ const Gcalc_scan_iterator *si);
+ int end_line(active_thread *t, const Gcalc_scan_iterator *si);
+ int connect_threads(int incoming_a, int incoming_b,
+ active_thread *ta, active_thread *tb,
+ const Gcalc_scan_iterator::point *pa,
+ const Gcalc_scan_iterator::point *pb,
+ active_thread *prev_range,
+ const Gcalc_scan_iterator *si,
+ Gcalc_function::shape_type s_t);
+ int add_single_point(const Gcalc_scan_iterator *si);
+ poly_border *get_pair_border(poly_border *b1);
+ int continue_range(active_thread *t, const Gcalc_heap::Info *p,
+ const Gcalc_heap::Info *p_next);
+ int continue_i_range(active_thread *t,
+ const Gcalc_heap::Info *ii);
+ int end_couple(active_thread *t0, active_thread *t1, const Gcalc_heap::Info *p);
+ int get_single_result(res_point *res, Gcalc_result_receiver *storage);
+ int get_result_thread(res_point *cur, Gcalc_result_receiver *storage,
+ int move_upward, res_point *first_poly_node);
+ int get_polygon_result(res_point *cur, Gcalc_result_receiver *storage,
+ res_point *first_poly_node);
+ int get_line_result(res_point *cur, Gcalc_result_receiver *storage);
+
+ void free_result(res_point *res);
+};
+
+#endif /*GCALC_TOOLS_INCLUDED*/
+
diff --git a/sql/gstream.cc b/sql/gstream.cc
index 61263380411..3a9e478c376 100644
--- a/sql/gstream.cc
+++ b/sql/gstream.cc
@@ -41,6 +41,29 @@ enum Gis_read_stream::enum_tok_types Gis_read_stream::get_next_toc_type()
}
+bool Gis_read_stream::lookup_next_word(LEX_STRING *res)
+{
+ const char *cur= m_cur;
+
+ skip_space();
+ res->str= (char*) cur;
+ /* The following will also test for \0 */
+ if ((cur >= m_limit) || !my_isvar_start(&my_charset_bin, *cur))
+ return 1;
+
+ /*
+ We can't combine the following increment with my_isvar() because
+ my_isvar() is a macro that would cause side effects
+ */
+ cur++;
+ while ((cur < m_limit) && my_isvar(&my_charset_bin, *cur))
+ cur++;
+
+ res->length= (uint32) (cur - res->str);
+ return 0;
+}
+
+
bool Gis_read_stream::get_next_word(LEX_STRING *res)
{
skip_space();
diff --git a/sql/gstream.h b/sql/gstream.h
index 533fafa28f3..f10b7e9b830 100644
--- a/sql/gstream.h
+++ b/sql/gstream.h
@@ -46,6 +46,7 @@ public:
}
enum enum_tok_types get_next_toc_type();
+ bool lookup_next_word(LEX_STRING *res);
bool get_next_word(LEX_STRING *);
bool get_next_number(double *);
bool check_next_symbol(char);
@@ -64,6 +65,14 @@ public:
m_cur++;
return 0;
}
+ /* Returns the next notempty character. */
+ char next_symbol()
+ {
+ skip_space();
+ if (m_cur >= m_limit)
+ return 0; /* EOL meet. */
+ return *m_cur;
+ }
void set_error_msg(const char *msg);
// caller should free this pointer
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 315ca857f6f..9c8d6b73e60 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -580,6 +580,19 @@ protected:
#ifdef HAVE_SPATIAL
+class Create_func_mbr_contains : public Create_func_arg2
+{
+ public:
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_mbr_contains s_singleton;
+
+ protected:
+ Create_func_mbr_contains() {}
+ virtual ~Create_func_mbr_contains() {}
+};
+
+
class Create_func_contains : public Create_func_arg2
{
public:
@@ -820,6 +833,19 @@ protected:
#ifdef HAVE_SPATIAL
+class Create_func_mbr_disjoint : public Create_func_arg2
+{
+ public:
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_mbr_disjoint s_singleton;
+
+ protected:
+ Create_func_mbr_disjoint() {}
+ virtual ~Create_func_mbr_disjoint() {}
+};
+
+
class Create_func_disjoint : public Create_func_arg2
{
public:
@@ -831,6 +857,19 @@ protected:
Create_func_disjoint() {}
virtual ~Create_func_disjoint() {}
};
+
+
+class Create_func_distance : public Create_func_arg2
+{
+ public:
+ virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_distance s_singleton;
+
+ protected:
+ Create_func_distance() {}
+ virtual ~Create_func_distance() {}
+};
#endif
@@ -904,6 +943,19 @@ protected:
#ifdef HAVE_SPATIAL
+class Create_func_mbr_equals : public Create_func_arg2
+{
+ public:
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_mbr_equals s_singleton;
+
+ protected:
+ Create_func_mbr_equals() {}
+ virtual ~Create_func_mbr_equals() {}
+};
+
+
class Create_func_equals : public Create_func_arg2
{
public:
@@ -1232,6 +1284,19 @@ protected:
#ifdef HAVE_SPATIAL
+class Create_func_mbr_intersects : public Create_func_arg2
+{
+ public:
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_mbr_intersects s_singleton;
+
+ protected:
+ Create_func_mbr_intersects() {}
+ virtual ~Create_func_mbr_intersects() {}
+};
+
+
class Create_func_intersects : public Create_func_arg2
{
public:
@@ -1243,7 +1308,72 @@ protected:
Create_func_intersects() {}
virtual ~Create_func_intersects() {}
};
-#endif
+
+
+class Create_func_intersection : public Create_func_arg2
+{
+public:
+ virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_intersection s_singleton;
+
+protected:
+ Create_func_intersection() {}
+ virtual ~Create_func_intersection() {}
+};
+
+
+class Create_func_difference : public Create_func_arg2
+{
+public:
+ virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_difference s_singleton;
+
+protected:
+ Create_func_difference() {}
+ virtual ~Create_func_difference() {}
+};
+
+
+class Create_func_union : public Create_func_arg2
+{
+public:
+ virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_union s_singleton;
+
+protected:
+ Create_func_union() {}
+ virtual ~Create_func_union() {}
+};
+
+
+class Create_func_symdifference : public Create_func_arg2
+{
+public:
+ virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_symdifference s_singleton;
+
+protected:
+ Create_func_symdifference() {}
+ virtual ~Create_func_symdifference() {}
+};
+
+
+class Create_func_buffer : public Create_func_arg2
+{
+public:
+ virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_buffer s_singleton;
+
+protected:
+ Create_func_buffer() {}
+ virtual ~Create_func_buffer() {}
+};
+#endif /*HAVE_SPATIAL*/
class Create_func_is_free_lock : public Create_func_arg1
@@ -1703,6 +1833,19 @@ protected:
#ifdef HAVE_SPATIAL
+class Create_func_mbr_overlaps : public Create_func_arg2
+{
+ public:
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_mbr_overlaps s_singleton;
+
+ protected:
+ Create_func_mbr_overlaps() {}
+ virtual ~Create_func_mbr_overlaps() {}
+};
+
+
class Create_func_overlaps : public Create_func_arg2
{
public:
@@ -2323,6 +2466,19 @@ protected:
#ifdef HAVE_SPATIAL
+class Create_func_mbr_within : public Create_func_arg2
+{
+ public:
+ virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
+
+ static Create_func_mbr_within s_singleton;
+
+ protected:
+ Create_func_mbr_within() {}
+ virtual ~Create_func_mbr_within() {}
+};
+
+
class Create_func_within : public Create_func_arg2
{
public:
@@ -3015,6 +3171,16 @@ Create_func_connection_id::create_builder(THD *thd)
#ifdef HAVE_SPATIAL
+Create_func_mbr_contains Create_func_mbr_contains::s_singleton;
+
+Item*
+Create_func_mbr_contains::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
+ Item_func::SP_CONTAINS_FUNC);
+}
+
+
Create_func_contains Create_func_contains::s_singleton;
Item*
@@ -3245,6 +3411,16 @@ Create_func_dimension::create_1_arg(THD *thd, Item *arg1)
#ifdef HAVE_SPATIAL
+Create_func_mbr_disjoint Create_func_mbr_disjoint::s_singleton;
+
+Item*
+Create_func_mbr_disjoint::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
+ Item_func::SP_DISJOINT_FUNC);
+}
+
+
Create_func_disjoint Create_func_disjoint::s_singleton;
Item*
@@ -3253,6 +3429,15 @@ Create_func_disjoint::create_2_arg(THD *thd, Item *arg1, Item *arg2)
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_DISJOINT_FUNC);
}
+
+
+Create_func_distance Create_func_distance::s_singleton;
+
+Item*
+Create_func_distance::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_distance(arg1, arg2);
+}
#endif
@@ -3348,6 +3533,16 @@ Create_func_envelope::create_1_arg(THD *thd, Item *arg1)
#ifdef HAVE_SPATIAL
+Create_func_mbr_equals Create_func_mbr_equals::s_singleton;
+
+Item*
+Create_func_mbr_equals::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
+ Item_func::SP_EQUALS_FUNC);
+}
+
+
Create_func_equals Create_func_equals::s_singleton;
Item*
@@ -3769,6 +3964,16 @@ Create_func_interiorringn::create_2_arg(THD *thd, Item *arg1, Item *arg2)
#ifdef HAVE_SPATIAL
+Create_func_mbr_intersects Create_func_mbr_intersects::s_singleton;
+
+Item*
+Create_func_mbr_intersects::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
+ Item_func::SP_INTERSECTS_FUNC);
+}
+
+
Create_func_intersects Create_func_intersects::s_singleton;
Item*
@@ -3777,7 +3982,56 @@ Create_func_intersects::create_2_arg(THD *thd, Item *arg1, Item *arg2)
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
Item_func::SP_INTERSECTS_FUNC);
}
-#endif
+
+
+Create_func_intersection Create_func_intersection::s_singleton;
+
+Item*
+Create_func_intersection::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_operation(arg1, arg2,
+ Gcalc_function::op_intersection);
+}
+
+
+Create_func_difference Create_func_difference::s_singleton;
+
+Item*
+Create_func_difference::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_operation(arg1, arg2,
+ Gcalc_function::op_difference);
+}
+
+
+Create_func_union Create_func_union::s_singleton;
+
+Item*
+Create_func_union::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_operation(arg1, arg2,
+ Gcalc_function::op_union);
+}
+
+
+Create_func_symdifference Create_func_symdifference::s_singleton;
+
+Item*
+Create_func_symdifference::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_operation(arg1, arg2,
+ Gcalc_function::op_symdifference);
+}
+
+
+Create_func_buffer Create_func_buffer::s_singleton;
+
+Item*
+Create_func_buffer::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_buffer(arg1, arg2);
+}
+#endif /*HAVE_SPATAI*/
Create_func_is_free_lock Create_func_is_free_lock::s_singleton;
@@ -4258,6 +4512,16 @@ Create_func_ord::create_1_arg(THD *thd, Item *arg1)
#ifdef HAVE_SPATIAL
+Create_func_mbr_overlaps Create_func_mbr_overlaps::s_singleton;
+
+Item*
+Create_func_mbr_overlaps::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
+ Item_func::SP_OVERLAPS_FUNC);
+}
+
+
Create_func_overlaps Create_func_overlaps::s_singleton;
Item*
@@ -4831,6 +5095,16 @@ Create_func_weekofyear::create_1_arg(THD *thd, Item *arg1)
#ifdef HAVE_SPATIAL
+Create_func_mbr_within Create_func_mbr_within::s_singleton;
+
+Item*
+Create_func_mbr_within::create_2_arg(THD *thd, Item *arg1, Item *arg2)
+{
+ return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
+ Item_func::SP_WITHIN_FUNC);
+}
+
+
Create_func_within Create_func_within::s_singleton;
Item*
@@ -4964,6 +5238,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("BIN") }, BUILDER(Create_func_bin)},
{ { C_STRING_WITH_LEN("BIT_COUNT") }, BUILDER(Create_func_bit_count)},
{ { C_STRING_WITH_LEN("BIT_LENGTH") }, BUILDER(Create_func_bit_length)},
+ { { C_STRING_WITH_LEN("BUFFER") }, GEOM_BUILDER(Create_func_buffer)},
{ { C_STRING_WITH_LEN("CEIL") }, BUILDER(Create_func_ceiling)},
{ { C_STRING_WITH_LEN("CEILING") }, BUILDER(Create_func_ceiling)},
{ { C_STRING_WITH_LEN("CENTROID") }, GEOM_BUILDER(Create_func_centroid)},
@@ -4991,7 +5266,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("DES_DECRYPT") }, BUILDER(Create_func_des_decrypt)},
{ { C_STRING_WITH_LEN("DES_ENCRYPT") }, BUILDER(Create_func_des_encrypt)},
{ { C_STRING_WITH_LEN("DIMENSION") }, GEOM_BUILDER(Create_func_dimension)},
- { { C_STRING_WITH_LEN("DISJOINT") }, GEOM_BUILDER(Create_func_disjoint)},
+ { { C_STRING_WITH_LEN("DISJOINT") }, GEOM_BUILDER(Create_func_mbr_disjoint)},
{ { C_STRING_WITH_LEN("ELT") }, BUILDER(Create_func_elt)},
{ { C_STRING_WITH_LEN("ENCODE") }, BUILDER(Create_func_encode)},
{ { C_STRING_WITH_LEN("ENCRYPT") }, BUILDER(Create_func_encrypt)},
@@ -5028,7 +5303,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("INET_NTOA") }, BUILDER(Create_func_inet_ntoa)},
{ { C_STRING_WITH_LEN("INSTR") }, BUILDER(Create_func_instr)},
{ { C_STRING_WITH_LEN("INTERIORRINGN") }, GEOM_BUILDER(Create_func_interiorringn)},
- { { C_STRING_WITH_LEN("INTERSECTS") }, GEOM_BUILDER(Create_func_intersects)},
+ { { C_STRING_WITH_LEN("INTERSECTS") }, GEOM_BUILDER(Create_func_mbr_intersects)},
{ { C_STRING_WITH_LEN("ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
{ { C_STRING_WITH_LEN("ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
{ { C_STRING_WITH_LEN("ISNULL") }, BUILDER(Create_func_isnull)},
@@ -5061,13 +5336,13 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("MAKETIME") }, BUILDER(Create_func_maketime)},
{ { C_STRING_WITH_LEN("MAKE_SET") }, BUILDER(Create_func_make_set)},
{ { C_STRING_WITH_LEN("MASTER_POS_WAIT") }, BUILDER(Create_func_master_pos_wait)},
- { { C_STRING_WITH_LEN("MBRCONTAINS") }, GEOM_BUILDER(Create_func_contains)},
- { { C_STRING_WITH_LEN("MBRDISJOINT") }, GEOM_BUILDER(Create_func_disjoint)},
- { { C_STRING_WITH_LEN("MBREQUAL") }, GEOM_BUILDER(Create_func_equals)},
- { { C_STRING_WITH_LEN("MBRINTERSECTS") }, GEOM_BUILDER(Create_func_intersects)},
- { { C_STRING_WITH_LEN("MBROVERLAPS") }, GEOM_BUILDER(Create_func_overlaps)},
+ { { C_STRING_WITH_LEN("MBRCONTAINS") }, GEOM_BUILDER(Create_func_mbr_contains)},
+ { { C_STRING_WITH_LEN("MBRDISJOINT") }, GEOM_BUILDER(Create_func_mbr_disjoint)},
+ { { C_STRING_WITH_LEN("MBREQUAL") }, GEOM_BUILDER(Create_func_mbr_equals)},
+ { { C_STRING_WITH_LEN("MBRINTERSECTS") }, GEOM_BUILDER(Create_func_mbr_intersects)},
+ { { C_STRING_WITH_LEN("MBROVERLAPS") }, GEOM_BUILDER(Create_func_mbr_overlaps)},
{ { C_STRING_WITH_LEN("MBRTOUCHES") }, GEOM_BUILDER(Create_func_touches)},
- { { C_STRING_WITH_LEN("MBRWITHIN") }, GEOM_BUILDER(Create_func_within)},
+ { { C_STRING_WITH_LEN("MBRWITHIN") }, GEOM_BUILDER(Create_func_mbr_within)},
{ { C_STRING_WITH_LEN("MD5") }, BUILDER(Create_func_md5)},
{ { C_STRING_WITH_LEN("MLINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
{ { C_STRING_WITH_LEN("MLINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
@@ -5090,7 +5365,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("OCT") }, BUILDER(Create_func_oct)},
{ { C_STRING_WITH_LEN("OCTET_LENGTH") }, BUILDER(Create_func_length)},
{ { C_STRING_WITH_LEN("ORD") }, BUILDER(Create_func_ord)},
- { { C_STRING_WITH_LEN("OVERLAPS") }, GEOM_BUILDER(Create_func_overlaps)},
+ { { C_STRING_WITH_LEN("OVERLAPS") }, GEOM_BUILDER(Create_func_mbr_overlaps)},
{ { C_STRING_WITH_LEN("PERIOD_ADD") }, BUILDER(Create_func_period_add)},
{ { C_STRING_WITH_LEN("PERIOD_DIFF") }, BUILDER(Create_func_period_diff)},
{ { C_STRING_WITH_LEN("PI") }, BUILDER(Create_func_pi)},
@@ -5126,6 +5401,64 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("STARTPOINT") }, GEOM_BUILDER(Create_func_startpoint)},
{ { C_STRING_WITH_LEN("STRCMP") }, BUILDER(Create_func_strcmp)},
{ { C_STRING_WITH_LEN("STR_TO_DATE") }, BUILDER(Create_func_str_to_date)},
+ { { C_STRING_WITH_LEN("ST_AREA") }, GEOM_BUILDER(Create_func_area)},
+ { { C_STRING_WITH_LEN("ST_ASBINARY") }, GEOM_BUILDER(Create_func_as_wkb)},
+ { { C_STRING_WITH_LEN("ST_ASTEXT") }, GEOM_BUILDER(Create_func_as_wkt)},
+ { { C_STRING_WITH_LEN("ST_ASWKB") }, GEOM_BUILDER(Create_func_as_wkb)},
+ { { C_STRING_WITH_LEN("ST_ASWKT") }, GEOM_BUILDER(Create_func_as_wkt)},
+ { { C_STRING_WITH_LEN("ST_BUFFER") }, GEOM_BUILDER(Create_func_buffer)},
+ { { C_STRING_WITH_LEN("ST_CENTROID") }, GEOM_BUILDER(Create_func_centroid)},
+ { { C_STRING_WITH_LEN("ST_CONTAINS") }, GEOM_BUILDER(Create_func_contains)},
+ { { C_STRING_WITH_LEN("ST_CROSSES") }, GEOM_BUILDER(Create_func_crosses)},
+ { { C_STRING_WITH_LEN("ST_DIFFERENCE") }, GEOM_BUILDER(Create_func_difference)},
+ { { C_STRING_WITH_LEN("ST_DIMENSION") }, GEOM_BUILDER(Create_func_dimension)},
+ { { C_STRING_WITH_LEN("ST_DISJOINT") }, GEOM_BUILDER(Create_func_disjoint)},
+ { { C_STRING_WITH_LEN("ST_DISTANCE") }, GEOM_BUILDER(Create_func_distance)},
+ { { C_STRING_WITH_LEN("ST_ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
+ { { C_STRING_WITH_LEN("ST_ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)},
+ { { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_equals)},
+ { { C_STRING_WITH_LEN("ST_EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
+ { { C_STRING_WITH_LEN("ST_GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
+ { { C_STRING_WITH_LEN("ST_GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
+ { { C_STRING_WITH_LEN("ST_GEOMETRYCOLLECTIONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
+ { { C_STRING_WITH_LEN("ST_GEOMETRYCOLLECTIONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
+ { { C_STRING_WITH_LEN("ST_GEOMETRYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
+ { { C_STRING_WITH_LEN("ST_GEOMETRYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
+ { { C_STRING_WITH_LEN("ST_GEOMETRYN") }, GEOM_BUILDER(Create_func_geometryn)},
+ { { C_STRING_WITH_LEN("ST_GEOMETRYTYPE") }, GEOM_BUILDER(Create_func_geometry_type)},
+ { { C_STRING_WITH_LEN("ST_GEOMFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
+ { { C_STRING_WITH_LEN("ST_GEOMFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
+ { { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_equals)},
+ { { C_STRING_WITH_LEN("ST_INTERIORRINGN") }, GEOM_BUILDER(Create_func_interiorringn)},
+ { { C_STRING_WITH_LEN("ST_INTERSECTS") }, GEOM_BUILDER(Create_func_intersects)},
+ { { C_STRING_WITH_LEN("ST_INTERSECTION") }, GEOM_BUILDER(Create_func_intersection)},
+ { { C_STRING_WITH_LEN("ST_ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
+ { { C_STRING_WITH_LEN("ST_ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
+ { { C_STRING_WITH_LEN("ST_ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
+ { { C_STRING_WITH_LEN("ST_LENGTH") }, GEOM_BUILDER(Create_func_glength)},
+ { { C_STRING_WITH_LEN("ST_LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
+ { { C_STRING_WITH_LEN("ST_LINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
+ { { C_STRING_WITH_LEN("ST_LINESTRINGFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
+ { { C_STRING_WITH_LEN("ST_LINESTRINGFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
+ { { C_STRING_WITH_LEN("ST_NUMGEOMETRIES") }, GEOM_BUILDER(Create_func_numgeometries)},
+ { { C_STRING_WITH_LEN("ST_NUMINTERIORRINGS") }, GEOM_BUILDER(Create_func_numinteriorring)},
+ { { C_STRING_WITH_LEN("ST_NUMPOINTS") }, GEOM_BUILDER(Create_func_numpoints)},
+ { { C_STRING_WITH_LEN("ST_OVERLAPS") }, GEOM_BUILDER(Create_func_overlaps)},
+ { { C_STRING_WITH_LEN("ST_POINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
+ { { C_STRING_WITH_LEN("ST_POINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
+ { { C_STRING_WITH_LEN("ST_POINTN") }, GEOM_BUILDER(Create_func_pointn)},
+ { { C_STRING_WITH_LEN("ST_POLYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
+ { { C_STRING_WITH_LEN("ST_POLYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
+ { { C_STRING_WITH_LEN("ST_POLYGONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
+ { { C_STRING_WITH_LEN("ST_POLYGONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
+ { { C_STRING_WITH_LEN("ST_SRID") }, GEOM_BUILDER(Create_func_srid)},
+ { { C_STRING_WITH_LEN("ST_STARTPOINT") }, GEOM_BUILDER(Create_func_startpoint)},
+ { { C_STRING_WITH_LEN("ST_SYMDIFFERENCE") }, GEOM_BUILDER(Create_func_symdifference)},
+ { { C_STRING_WITH_LEN("ST_TOUCHES") }, GEOM_BUILDER(Create_func_touches)},
+ { { C_STRING_WITH_LEN("ST_UNION") }, GEOM_BUILDER(Create_func_union)},
+ { { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_within)},
+ { { C_STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)},
+ { { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)},
{ { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)},
{ { C_STRING_WITH_LEN("SUBTIME") }, BUILDER(Create_func_subtime)},
{ { C_STRING_WITH_LEN("TAN") }, BUILDER(Create_func_tan)},
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 621ddcb1a30..5ccdb198ecb 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates.
+ Copyright (C) 2011 Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -36,6 +37,7 @@
#ifdef HAVE_SPATIAL
#include <m_ctype.h>
+
Field *Item_geometry_func::tmp_table_field(TABLE *t_arg)
{
Field *result;
@@ -368,8 +370,8 @@ String *Item_func_point::val_str(String *str)
uint32 srid= 0;
if ((null_value= (args[0]->null_value ||
- args[1]->null_value ||
- str->realloc(4/*SRID*/ + 1 + 4 + SIZEOF_STORED_DOUBLE*2))))
+ args[1]->null_value ||
+ str->realloc(4/*SRID*/ + 1 + 4 + SIZEOF_STORED_DOUBLE * 2))))
return 0;
str->set_charset(&my_charset_bin);
@@ -516,7 +518,33 @@ err:
Functions for spatial relations
*/
-longlong Item_func_spatial_rel::val_int()
+const char *Item_func_spatial_mbr_rel::func_name() const
+{
+ switch (spatial_rel) {
+ case SP_CONTAINS_FUNC:
+ return "mbrcontains";
+ case SP_WITHIN_FUNC:
+ return "mbrwithin";
+ case SP_EQUALS_FUNC:
+ return "mbrequals";
+ case SP_DISJOINT_FUNC:
+ return "mbrdisjoint";
+ case SP_INTERSECTS_FUNC:
+ return "mbrintersects";
+ case SP_TOUCHES_FUNC:
+ return "mbrtouches";
+ case SP_CROSSES_FUNC:
+ return "mbrcrosses";
+ case SP_OVERLAPS_FUNC:
+ return "mbroverlaps";
+ default:
+ DBUG_ASSERT(0); // Should never happened
+ return "mbrsp_unknown";
+ }
+}
+
+
+longlong Item_func_spatial_mbr_rel::val_int()
{
DBUG_ASSERT(fixed == 1);
String *res1= args[0]->val_str(&cmp.value1);
@@ -561,6 +589,844 @@ longlong Item_func_spatial_rel::val_int()
}
+Item_func_spatial_rel::Item_func_spatial_rel(Item *a,Item *b,
+ enum Functype sp_rel) :
+ Item_bool_func2(a,b), collector()
+{
+ spatial_rel = sp_rel;
+}
+
+
+Item_func_spatial_rel::~Item_func_spatial_rel()
+{
+}
+
+
+const char *Item_func_spatial_rel::func_name() const
+{
+ switch (spatial_rel) {
+ case SP_CONTAINS_FUNC:
+ return "st_contains";
+ case SP_WITHIN_FUNC:
+ return "st_within";
+ case SP_EQUALS_FUNC:
+ return "st_equals";
+ case SP_DISJOINT_FUNC:
+ return "st_disjoint";
+ case SP_INTERSECTS_FUNC:
+ return "st_intersects";
+ case SP_TOUCHES_FUNC:
+ return "st_touches";
+ case SP_CROSSES_FUNC:
+ return "st_crosses";
+ case SP_OVERLAPS_FUNC:
+ return "st_overlaps";
+ default:
+ DBUG_ASSERT(0); // Should never happened
+ return "sp_unknown";
+ }
+}
+
+
+static double count_edge_t(const Gcalc_heap::Info *ea,
+ const Gcalc_heap::Info *eb,
+ const Gcalc_heap::Info *v,
+ double &ex, double &ey, double &vx, double &vy,
+ double &e_sqrlen)
+{
+ ex= eb->x - ea->x;
+ ey= eb->y - ea->y;
+ vx= v->x - ea->x;
+ vy= v->y - ea->y;
+ e_sqrlen= ex * ex + ey * ey;
+ return (ex * vx + ey * vy) / e_sqrlen;
+}
+
+
+static double distance_to_line(double ex, double ey, double vx, double vy,
+ double e_sqrlen)
+{
+ return fabs(vx * ey - vy * ex) / sqrt(e_sqrlen);
+}
+
+
+static double distance_points(const Gcalc_heap::Info *a,
+ const Gcalc_heap::Info *b)
+{
+ double x= a->x - b->x;
+ double y= a->y - b->y;
+ return sqrt(x * x + y * y);
+}
+
+
+/*
+ Calculates the distance between objects.
+*/
+
+#ifdef TMP_BLOCK
+static int calc_distance(double *result, Gcalc_heap *collector, uint obj2_si,
+ Gcalc_function *func, Gcalc_scan_iterator *scan_it)
+{
+ bool above_cur_point, cur_point_edge;
+ const Gcalc_scan_iterator::point *evpos;
+ const Gcalc_heap::Info *cur_point= NULL;
+ const Gcalc_heap::Info *dist_point;
+ const Gcalc_scan_iterator::point *ev;
+ double t, distance, cur_distance;
+ double ex, ey, vx, vy, e_sqrlen;
+ int o1, o2;
+
+ DBUG_ENTER("calc_distance");
+
+ above_cur_point= false;
+ distance= DBL_MAX;
+
+ while (scan_it->more_points())
+ {
+ if (scan_it->step())
+ goto mem_error;
+ evpos= scan_it->get_event_position();
+ ev= scan_it->get_events();
+ cur_point= NULL;
+
+ if (ev->simple_event())
+ {
+ cur_point= ev->pi;
+ goto calculate_distance;
+ }
+
+ /*
+ handling intersection we only need to check if it's the intersecion
+ of objects 1 and 2. In this case distance is 0
+ */
+ o1= 0;
+ o2= 0;
+ for (; ev; ev= ev->get_next())
+ {
+ if (ev->event != scev_intersection)
+ cur_point= ev->pi;
+ if (ev->pi->shape >= obj2_si)
+ o2= 1;
+ else
+ o1= 1;
+ if (o1 && o2)
+ {
+ distance= 0;
+ goto exit;
+ }
+ }
+ if (!cur_point)
+ continue;
+
+#ifdef TO_REMOVE
+ goto calculate_distance;
+ /*
+ having these events we need to check for possible intersection
+ of objects
+ scev_thread | scev_two_threads | scev_single_point
+ */
+ DBUG_ASSERT(ev & (scev_thread | scev_two_threads | scev_single_point));
+
+ func->clear_state();
+ for (Gcalc_point_iterator pit(scan_it); pit.point() != evpos; ++pit)
+ {
+ gcalc_shape_info si= pit.point()->get_shape();
+ if ((func->get_shape_kind(si) == Gcalc_function::shape_polygon))
+ func->invert_state(si);
+ }
+ func->invert_state(evpos->get_shape());
+ if (func->count())
+ {
+ /* Point of one object is inside the other - intersection found */
+ distance= 0;
+ goto exit;
+ }
+#endif /*TO_REMOVE*/
+
+calculate_distance:
+ if (cur_point->shape >= obj2_si)
+ continue;
+ cur_point_edge= !cur_point->is_bottom();
+
+ for (dist_point= collector->get_first(); dist_point; dist_point= dist_point->get_next())
+ {
+ /* We only check vertices of object 2 */
+ if (dist_point->shape < obj2_si)
+ continue;
+
+ /* if we have an edge to check */
+ if (dist_point->left)
+ {
+ t= count_edge_t(dist_point, dist_point->left, cur_point,
+ ex, ey, vx, vy, e_sqrlen);
+ if ((t > 0.0) && (t < 1.0))
+ {
+ cur_distance= distance_to_line(ex, ey, vx, vy, e_sqrlen);
+ if (distance > cur_distance)
+ distance= cur_distance;
+ }
+ }
+ if (cur_point_edge)
+ {
+ t= count_edge_t(cur_point, cur_point->left, dist_point,
+ ex, ey, vx, vy, e_sqrlen);
+ if ((t > 0.0) && (t < 1.0))
+ {
+ cur_distance= distance_to_line(ex, ey, vx, vy, e_sqrlen);
+ if (distance > cur_distance)
+ distance= cur_distance;
+ }
+ }
+ cur_distance= distance_points(cur_point, dist_point);
+ if (distance > cur_distance)
+ distance= cur_distance;
+ }
+ }
+
+exit:
+ *result= distance;
+ DBUG_RETURN(0);
+
+mem_error:
+ DBUG_RETURN(1);
+}
+#endif /*TMP_BLOCK*/
+
+
+#define GIS_ZERO 0.00000000001
+
+longlong Item_func_spatial_rel::val_int()
+{
+ DBUG_ENTER("Item_func_spatial_rel::val_int");
+ DBUG_ASSERT(fixed == 1);
+ String *res1;
+ String *res2;
+ Geometry_buffer buffer1, buffer2;
+ Geometry *g1, *g2;
+ int result= 0;
+ int mask= 0;
+ uint shape_a, shape_b;
+
+ res1= args[0]->val_str(&tmp_value1);
+ res2= args[1]->val_str(&tmp_value2);
+ Gcalc_operation_transporter trn(&func, &collector);
+
+ if (func.reserve_op_buffer(1))
+ DBUG_RETURN(0);
+
+ if ((null_value=
+ (args[0]->null_value || args[1]->null_value ||
+ !(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
+ !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())))))
+ goto exit;
+
+ switch (spatial_rel) {
+ case SP_CONTAINS_FUNC:
+ mask= 1;
+ func.add_operation(Gcalc_function::op_difference, 2);
+ /* Mind the g2 goes first. */
+ null_value= g2->store_shapes(&trn) || g1->store_shapes(&trn);
+ break;
+ case SP_WITHIN_FUNC:
+ mask= 1;
+ func.add_operation(Gcalc_function::op_difference, 2);
+ null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
+ break;
+ case SP_EQUALS_FUNC:
+ mask= 1;
+ func.add_operation(Gcalc_function::op_symdifference, 2);
+ null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
+ break;
+ case SP_DISJOINT_FUNC:
+ mask= 1;
+ func.add_operation(Gcalc_function::op_intersection, 2);
+ null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
+ break;
+ case SP_INTERSECTS_FUNC:
+ func.add_operation(Gcalc_function::op_intersection, 2);
+ null_value= g1->store_shapes(&trn) || g2->store_shapes(&trn);
+ break;
+ case SP_OVERLAPS_FUNC:
+ case SP_CROSSES_FUNC:
+ func.add_operation(Gcalc_function::op_intersection, 2);
+ func.add_operation(Gcalc_function::v_find_t |
+ Gcalc_function::op_intersection, 2);
+ shape_a= func.get_next_expression_pos();
+ if ((null_value= g1->store_shapes(&trn)))
+ break;
+ shape_b= func.get_next_expression_pos();
+ if ((null_value= g2->store_shapes(&trn)))
+ break;
+ func.add_operation(Gcalc_function::v_find_t |
+ Gcalc_function::op_intersection, 2);
+ func.add_operation(Gcalc_function::v_find_t |
+ Gcalc_function::op_difference, 2);
+ func.repeat_expression(shape_a);
+ func.repeat_expression(shape_b);
+ func.add_operation(Gcalc_function::v_find_t |
+ Gcalc_function::op_difference, 2);
+ func.repeat_expression(shape_b);
+ func.repeat_expression(shape_a);
+ break;
+ case SP_TOUCHES_FUNC:
+ func.add_operation(Gcalc_function::op_intersection, 2);
+ func.add_operation(Gcalc_function::v_find_f |
+ Gcalc_function::op_not |
+ Gcalc_function::op_intersection, 2);
+ func.add_operation(Gcalc_function::op_internals, 1);
+ shape_a= func.get_next_expression_pos();
+ if ((null_value= g1->store_shapes(&trn)))
+ break;
+ func.add_operation(Gcalc_function::op_internals, 1);
+ shape_b= func.get_next_expression_pos();
+ if ((null_value= g2->store_shapes(&trn)))
+ break;
+ func.add_operation(Gcalc_function::v_find_t |
+ Gcalc_function::op_intersection, 2);
+ func.add_operation(Gcalc_function::op_border, 1);
+ func.repeat_expression(shape_a);
+ func.add_operation(Gcalc_function::op_border, 1);
+ func.repeat_expression(shape_b);
+ break;
+ default:
+ DBUG_ASSERT(FALSE);
+ break;
+ }
+
+ if (null_value)
+ goto exit;
+
+ collector.prepare_operation();
+ scan_it.init(&collector);
+ scan_it.killed= (int *) &(current_thd->killed);
+
+#ifdef TMP_BLOCK
+ if (spatial_rel == SP_EQUALS_FUNC)
+ {
+ result= (g1->get_class_info()->m_type_id == g1->get_class_info()->m_type_id) &&
+ func_equals();
+ goto exit;
+ }
+#endif /*TMP_BLOCK*/
+
+ if (func.alloc_states())
+ goto exit;
+
+ result= func.check_function(scan_it) ^ mask;
+
+exit:
+ collector.reset();
+ func.reset();
+ scan_it.reset();
+ DBUG_RETURN(result);
+}
+
+
+Item_func_spatial_operation::~Item_func_spatial_operation()
+{
+}
+
+
+String *Item_func_spatial_operation::val_str(String *str_value)
+{
+ DBUG_ENTER("Item_func_spatial_operation::val_str");
+ DBUG_ASSERT(fixed == 1);
+ String *res1= args[0]->val_str(&tmp_value1);
+ String *res2= args[1]->val_str(&tmp_value2);
+ Geometry_buffer buffer1, buffer2;
+ Geometry *g1, *g2;
+ uint32 srid= 0;
+ Gcalc_operation_transporter trn(&func, &collector);
+
+ if (func.reserve_op_buffer(1))
+ DBUG_RETURN(0);
+ func.add_operation(spatial_op, 2);
+
+ if ((null_value=
+ (args[0]->null_value || args[1]->null_value ||
+ !(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
+ !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())) ||
+ g1->store_shapes(&trn) || g2->store_shapes(&trn))))
+ {
+ str_value= 0;
+ goto exit;
+ }
+
+
+ collector.prepare_operation();
+ if (func.alloc_states())
+ goto exit;
+
+ operation.init(&func);
+
+ if (operation.count_all(&collector) ||
+ operation.get_result(&res_receiver))
+ goto exit;
+
+
+ str_value->set_charset(&my_charset_bin);
+ if (str_value->reserve(SRID_SIZE, 512))
+ goto exit;
+ str_value->length(0);
+ str_value->q_append(srid);
+
+ if (!Geometry::create_from_opresult(&buffer1, str_value, res_receiver))
+ goto exit;
+
+exit:
+ collector.reset();
+ func.reset();
+ res_receiver.reset();
+ DBUG_RETURN(str_value);
+}
+
+
+const char *Item_func_spatial_operation::func_name() const
+{
+ switch (spatial_op) {
+ case Gcalc_function::op_intersection:
+ return "st_intersection";
+ case Gcalc_function::op_difference:
+ return "st_difference";
+ case Gcalc_function::op_union:
+ return "st_union";
+ case Gcalc_function::op_symdifference:
+ return "st_symdifference";
+ default:
+ DBUG_ASSERT(0); // Should never happen
+ return "sp_unknown";
+ }
+}
+
+
+static const int SINUSES_CALCULATED= 32;
+static double n_sinus[SINUSES_CALCULATED+1]=
+{
+ 0,
+ 0.04906767432741802,
+ 0.0980171403295606,
+ 0.1467304744553618,
+ 0.1950903220161283,
+ 0.2429801799032639,
+ 0.2902846772544623,
+ 0.3368898533922201,
+ 0.3826834323650898,
+ 0.4275550934302821,
+ 0.4713967368259976,
+ 0.5141027441932217,
+ 0.5555702330196022,
+ 0.5956993044924334,
+ 0.6343932841636455,
+ 0.6715589548470183,
+ 0.7071067811865475,
+ 0.7409511253549591,
+ 0.773010453362737,
+ 0.8032075314806448,
+ 0.8314696123025452,
+ 0.8577286100002721,
+ 0.8819212643483549,
+ 0.9039892931234433,
+ 0.9238795325112867,
+ 0.9415440651830208,
+ 0.9569403357322089,
+ 0.970031253194544,
+ 0.9807852804032304,
+ 0.989176509964781,
+ 0.9951847266721968,
+ 0.9987954562051724,
+ 1
+};
+
+
+static void get_n_sincos(int n, double *sinus, double *cosinus)
+{
+ DBUG_ASSERT(n > 0 && n < SINUSES_CALCULATED*2+1);
+ if (n < (SINUSES_CALCULATED + 1))
+ {
+ *sinus= n_sinus[n];
+ *cosinus= n_sinus[SINUSES_CALCULATED - n];
+ }
+ else
+ {
+ n-= SINUSES_CALCULATED;
+ *sinus= n_sinus[SINUSES_CALCULATED - n];
+ *cosinus= -n_sinus[n];
+ }
+}
+
+
+static int fill_half_circle(Gcalc_shape_transporter *trn, double x, double y,
+ double ax, double ay)
+{
+ double n_sin, n_cos;
+ double x_n, y_n;
+ for (int n = 1; n < (SINUSES_CALCULATED * 2 - 1); n++)
+ {
+ get_n_sincos(n, &n_sin, &n_cos);
+ x_n= ax * n_cos - ay * n_sin;
+ y_n= ax * n_sin + ay * n_cos;
+ if (trn->add_point(x_n + x, y_n + y))
+ return 1;
+ }
+ return 0;
+}
+
+
+static int fill_gap(Gcalc_shape_transporter *trn,
+ double x, double y,
+ double ax, double ay, double bx, double by, double d,
+ bool *empty_gap)
+{
+ double ab= ax * bx + ay * by;
+ double cosab= ab / (d * d) + GIS_ZERO;
+ double n_sin, n_cos;
+ double x_n, y_n;
+ int n=1;
+
+ *empty_gap= true;
+ for (;;)
+ {
+ get_n_sincos(n++, &n_sin, &n_cos);
+ if (n_cos <= cosab)
+ break;
+ *empty_gap= false;
+ x_n= ax * n_cos - ay * n_sin;
+ y_n= ax * n_sin + ay * n_cos;
+ if (trn->add_point(x_n + x, y_n + y))
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ Calculates the vector (p2,p1) and
+ negatively orthogonal to it with the length of d.
+ The result is (ex,ey) - the vector, (px,py) - the orthogonal.
+*/
+
+static void calculate_perpendicular(
+ double x1, double y1, double x2, double y2, double d,
+ double *ex, double *ey,
+ double *px, double *py)
+{
+ double q;
+ *ex= x1 - x2;
+ *ey= y1 - y2;
+ q= d / sqrt((*ex) * (*ex) + (*ey) * (*ey));
+ *px= (*ey) * q;
+ *py= -(*ex) * q;
+}
+
+
+int Item_func_buffer::Transporter::single_point(double x, double y)
+{
+ return add_point_buffer(x, y);
+}
+
+
+int Item_func_buffer::Transporter::add_edge_buffer(
+ double x3, double y3, bool round_p1, bool round_p2)
+{
+ Gcalc_operation_transporter trn(m_fn, m_heap);
+ double e1_x, e1_y, e2_x, e2_y, p1_x, p1_y, p2_x, p2_y;
+ double e1e2;
+ double sin1, cos1;
+ double x_n, y_n;
+ bool empty_gap1, empty_gap2;
+
+ ++m_nshapes;
+ if (trn.start_simple_poly())
+ return 1;
+
+ calculate_perpendicular(x1, y1, x2, y2, m_d, &e1_x, &e1_y, &p1_x, &p1_y);
+ calculate_perpendicular(x3, y3, x2, y2, m_d, &e2_x, &e2_y, &p2_x, &p2_y);
+
+ e1e2= e1_x * e2_y - e2_x * e1_y;
+ sin1= n_sinus[1];
+ cos1= n_sinus[31];
+ if (e1e2 < 0)
+ {
+ empty_gap2= false;
+ x_n= x2 + p2_x * cos1 - p2_y * sin1;
+ y_n= y2 + p2_y * cos1 + p2_x * sin1;
+ if (fill_gap(&trn, x2, y2, -p1_x,-p1_y, p2_x,p2_y, m_d, &empty_gap1) ||
+ trn.add_point(x2 + p2_x, y2 + p2_y) ||
+ trn.add_point(x_n, y_n))
+ return 1;
+ }
+ else
+ {
+ x_n= x2 - p2_x * cos1 - p2_y * sin1;
+ y_n= y2 - p2_y * cos1 + p2_x * sin1;
+ if (trn.add_point(x_n, y_n) ||
+ trn.add_point(x2 - p2_x, y2 - p2_y) ||
+ fill_gap(&trn, x2, y2, -p2_x, -p2_y, p1_x, p1_y, m_d, &empty_gap2))
+ return 1;
+ empty_gap1= false;
+ }
+ if ((!empty_gap2 && trn.add_point(x2 + p1_x, y2 + p1_y)) ||
+ trn.add_point(x1 + p1_x, y1 + p1_y))
+ return 1;
+
+ if (round_p1 && fill_half_circle(&trn, x1, y1, p1_x, p1_y))
+ return 1;
+
+ if (trn.add_point(x1 - p1_x, y1 - p1_y) ||
+ (!empty_gap1 && trn.add_point(x2 - p1_x, y2 - p1_y)))
+ return 1;
+ return trn.complete_simple_poly();
+}
+
+
+int Item_func_buffer::Transporter::add_last_edge_buffer()
+{
+ Gcalc_operation_transporter trn(m_fn, m_heap);
+ double e1_x, e1_y, p1_x, p1_y;
+
+ ++m_nshapes;
+ if (trn.start_simple_poly())
+ return 1;
+
+ calculate_perpendicular(x1, y1, x2, y2, m_d, &e1_x, &e1_y, &p1_x, &p1_y);
+
+ if (trn.add_point(x1 + p1_x, y1 + p1_y) ||
+ trn.add_point(x1 - p1_x, y1 - p1_y) ||
+ trn.add_point(x2 - p1_x, y2 - p1_y) ||
+ fill_half_circle(&trn, x2, y2, -p1_x, -p1_y) ||
+ trn.add_point(x2 + p1_x, y2 + p1_y))
+ return 1;
+ return trn.complete_simple_poly();
+}
+
+
+int Item_func_buffer::Transporter::add_point_buffer(double x, double y)
+{
+ Gcalc_operation_transporter trn(m_fn, m_heap);
+
+ m_nshapes++;
+ if (trn.start_simple_poly())
+ return 1;
+ if (trn.add_point(x - m_d, y) ||
+ fill_half_circle(&trn, x, y, -m_d, 0.0) ||
+ trn.add_point(x + m_d, y) ||
+ fill_half_circle(&trn, x, y, m_d, 0.0))
+ return 1;
+ return trn.complete_simple_poly();
+}
+
+
+int Item_func_buffer::Transporter::start_line()
+{
+ if (buffer_op == Gcalc_function::op_difference)
+ {
+ skip_line= TRUE;
+ return 0;
+ }
+
+ m_nshapes= 0;
+
+ if (m_fn->reserve_op_buffer(2))
+ return 1;
+ last_shape_pos= m_fn->get_next_expression_pos();
+ m_fn->add_operation(buffer_op, 0);
+ m_npoints= 0;
+ int_start_line();
+ return 0;
+}
+
+
+int Item_func_buffer::Transporter::start_poly()
+{
+ m_nshapes= 1;
+
+ if (m_fn->reserve_op_buffer(2))
+ return 1;
+ last_shape_pos= m_fn->get_next_expression_pos();
+ m_fn->add_operation(buffer_op, 0);
+ return Gcalc_operation_transporter::start_poly();
+}
+
+
+int Item_func_buffer::Transporter::complete_poly()
+{
+ if (Gcalc_operation_transporter::complete_poly())
+ return 1;
+ m_fn->add_operands_to_op(last_shape_pos, m_nshapes);
+ return 0;
+}
+
+
+int Item_func_buffer::Transporter::start_ring()
+{
+ m_npoints= 0;
+ return Gcalc_operation_transporter::start_ring();
+}
+
+
+int Item_func_buffer::Transporter::start_collection(int n_objects)
+{
+ if (m_fn->reserve_op_buffer(1))
+ return 1;
+ m_fn->add_operation(Gcalc_function::op_union, n_objects);
+ return 0;
+}
+
+
+int Item_func_buffer::Transporter::add_point(double x, double y)
+{
+ if (skip_line)
+ return 0;
+
+ if (m_npoints && x == x2 && y == y2)
+ return 0;
+
+ ++m_npoints;
+
+ if (m_npoints == 1)
+ {
+ x00= x;
+ y00= y;
+ }
+ else if (m_npoints == 2)
+ {
+ x01= x;
+ y01= y;
+ }
+ else if (add_edge_buffer(x, y, (m_npoints == 3) && line_started(), false))
+ return 1;
+
+ x1= x2;
+ y1= y2;
+ x2= x;
+ y2= y;
+
+ return line_started() ? 0 : Gcalc_operation_transporter::add_point(x, y);
+}
+
+
+int Item_func_buffer::Transporter::complete()
+{
+ if (m_npoints)
+ {
+ if (m_npoints == 1)
+ {
+ if (add_point_buffer(x2, y2))
+ return 1;
+ }
+ else if (m_npoints == 2)
+ {
+ if (add_edge_buffer(x1, y1, true, true))
+ return 1;
+ }
+ else if (line_started())
+ {
+ if (add_last_edge_buffer())
+ return 1;
+ }
+ else
+ {
+ if (x2 != x00 || y2 != y00)
+ {
+ if (add_edge_buffer(x00, y00, false, false))
+ return 1;
+ x1= x2;
+ y1= y2;
+ x2= x00;
+ y2= y00;
+ }
+ if (add_edge_buffer(x01, y01, false, false))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+int Item_func_buffer::Transporter::complete_line()
+{
+ if (!skip_line)
+ {
+ if (complete())
+ return 1;
+ int_complete_line();
+ m_fn->add_operands_to_op(last_shape_pos, m_nshapes);
+ }
+ skip_line= FALSE;
+ return 0;
+}
+
+
+int Item_func_buffer::Transporter::complete_ring()
+{
+ return complete() ||
+ Gcalc_operation_transporter::complete_ring();
+}
+
+
+String *Item_func_buffer::val_str(String *str_value)
+{
+ DBUG_ENTER("Item_func_buffer::val_str");
+ DBUG_ASSERT(fixed == 1);
+ String *obj= args[0]->val_str(&tmp_value);
+ double dist= args[1]->val_real();
+ Geometry_buffer buffer;
+ Geometry *g;
+ uint32 srid= 0;
+ String *str_result= NULL;
+ Transporter trn(&func, &collector, dist);
+
+ null_value= 1;
+ if (args[0]->null_value || args[1]->null_value ||
+ !(g= Geometry::construct(&buffer, obj->ptr(), obj->length())))
+ goto mem_error;
+
+ /*
+ If the distance given is 0, the Buffer function is in fact NOOP,
+ so it's natural just to return the argument1.
+ Besides, internal calculations here can't handle zero distance anyway.
+ */
+ if (fabs(dist) < GIS_ZERO)
+ {
+ null_value= 0;
+ str_result= obj;
+ goto mem_error;
+ }
+
+ if (g->store_shapes(&trn))
+ goto mem_error;
+
+ collector.prepare_operation();
+ if (func.alloc_states())
+ goto mem_error;
+ operation.init(&func);
+ operation.killed= (int *) &(current_thd->killed);
+
+ if (operation.count_all(&collector) ||
+ operation.get_result(&res_receiver))
+ goto mem_error;
+
+
+ str_value->set_charset(&my_charset_bin);
+ if (str_value->reserve(SRID_SIZE, 512))
+ goto mem_error;
+ str_value->length(0);
+ str_value->q_append(srid);
+
+ if (!Geometry::create_from_opresult(&buffer, str_value, res_receiver))
+ goto mem_error;
+
+ null_value= 0;
+ str_result= str_value;
+mem_error:
+ collector.reset();
+ func.reset();
+ res_receiver.reset();
+ DBUG_RETURN(str_result);
+}
+
+
longlong Item_func_isempty::val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -574,21 +1440,59 @@ longlong Item_func_isempty::val_int()
}
-/**
- @todo
- Ramil or Holyfoot, add real IsSimple calculation
-*/
longlong Item_func_issimple::val_int()
{
- DBUG_ASSERT(fixed == 1);
- String tmp;
String *swkb= args[0]->val_str(&tmp);
Geometry_buffer buffer;
+ Gcalc_operation_transporter trn(&func, &collector);
+ Geometry *g;
+ int result= 1;
+ const Gcalc_scan_iterator::event_point *ev;
+
+ DBUG_ENTER("Item_func_issimple::val_int");
+ DBUG_ASSERT(fixed == 1);
- null_value= args[0]->null_value ||
- !(Geometry::construct(&buffer, swkb->ptr(), swkb->length()));
- /* TODO: Ramil or Holyfoot, add real IsSimple calculation */
- return 0;
+ if ((null_value= args[0]->null_value) ||
+ !(g= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))
+ DBUG_RETURN(0);
+
+
+ if (g->get_class_info()->m_type_id == Geometry::wkb_point)
+ DBUG_RETURN(1);
+
+ if (g->store_shapes(&trn))
+ goto mem_error;
+
+ collector.prepare_operation();
+ scan_it.init(&collector);
+
+ while (scan_it.more_points())
+ {
+ if (scan_it.step())
+ goto mem_error;
+
+ ev= scan_it.get_events();
+ if (ev->simple_event())
+ continue;
+
+ if ((ev->event == scev_thread || ev->event == scev_single_point) &&
+ !ev->get_next())
+ continue;
+
+ if (ev->event == scev_two_threads && !ev->get_next()->get_next())
+ continue;
+
+ result= 0;
+ break;
+ }
+
+ collector.reset();
+ func.reset();
+ scan_it.reset();
+ DBUG_RETURN(result);
+mem_error:
+ null_value= 1;
+ DBUG_RETURN(0);
}
@@ -736,12 +1640,13 @@ double Item_func_glength::val_real()
String *swkb= args[0]->val_str(&value);
Geometry_buffer buffer;
Geometry *geom;
+ const char *end;
null_value= (!swkb ||
!(geom= Geometry::construct(&buffer,
swkb->ptr(),
swkb->length())) ||
- geom->geom_length(&res));
+ geom->geom_length(&res, &end));
return res;
}
@@ -760,4 +1665,161 @@ longlong Item_func_srid::val_int()
return (longlong) (uint4korr(swkb->ptr()));
}
+
+double Item_func_distance::val_real()
+{
+ bool cur_point_edge;
+ const Gcalc_scan_iterator::point *evpos;
+ const Gcalc_heap::Info *cur_point, *dist_point;
+ const Gcalc_scan_iterator::event_point *ev;
+ double t, distance, cur_distance;
+ double x1, x2, y1, y2;
+ double ex, ey, vx, vy, e_sqrlen;
+ uint obj2_si;
+ Gcalc_operation_transporter trn(&func, &collector);
+
+ DBUG_ENTER("Item_func_distance::val_real");
+ DBUG_ASSERT(fixed == 1);
+ String *res1= args[0]->val_str(&tmp_value1);
+ String *res2= args[1]->val_str(&tmp_value2);
+ Geometry_buffer buffer1, buffer2;
+ Geometry *g1, *g2;
+
+
+ if ((null_value= (args[0]->null_value || args[1]->null_value ||
+ !(g1= Geometry::construct(&buffer1, res1->ptr(), res1->length())) ||
+ !(g2= Geometry::construct(&buffer2, res2->ptr(), res2->length())))))
+ goto mem_error;
+
+ if ((g1->get_class_info()->m_type_id == Geometry::wkb_point) &&
+ (g2->get_class_info()->m_type_id == Geometry::wkb_point))
+ {
+ if (((Gis_point *) g1)->get_xy(&x1, &y1) ||
+ ((Gis_point *) g2)->get_xy(&x2, &y2))
+ goto mem_error;
+ ex= x2 - x1;
+ ey= y2 - y1;
+ DBUG_RETURN(sqrt(ex * ex + ey * ey));
+ }
+
+ if (func.reserve_op_buffer(1))
+ goto mem_error;
+ func.add_operation(Gcalc_function::op_intersection, 2);
+
+ if (g1->store_shapes(&trn))
+ goto mem_error;
+ obj2_si= func.get_nshapes();
+ if (g2->store_shapes(&trn) || func.alloc_states())
+ goto mem_error;
+
+ if (obj2_si == 0 || func.get_nshapes() == obj2_si)
+ {
+ distance= 0.0;
+ null_value= 1;
+ goto exit;
+ }
+
+
+ collector.prepare_operation();
+ scan_it.init(&collector);
+
+ distance= DBL_MAX;
+ while (scan_it.more_points())
+ {
+ if (scan_it.step())
+ goto mem_error;
+ evpos= scan_it.get_event_position();
+ ev= scan_it.get_events();
+
+ if (ev->simple_event())
+ {
+ cur_point= ev->pi;
+ goto count_distance;
+ }
+ /*
+ handling intersection we only need to check if it's the intersecion
+ of objects 1 and 2. In this case distance is 0
+ */
+ cur_point= NULL;
+
+ /*
+ having these events we need to check for possible intersection
+ of objects
+ scev_thread | scev_two_threads | scev_single_point
+ */
+ func.clear_i_states();
+ for (Gcalc_point_iterator pit(&scan_it); pit.point() != evpos; ++pit)
+ {
+ gcalc_shape_info si= pit.point()->get_shape();
+ if ((func.get_shape_kind(si) == Gcalc_function::shape_polygon))
+ func.invert_i_state(si);
+ }
+
+ func.clear_b_states();
+ for (; ev; ev= ev->get_next())
+ {
+ if (ev->event != scev_intersection)
+ cur_point= ev->pi;
+ func.set_b_state(ev->get_shape());
+ if (func.count())
+ {
+ /* Point of one object is inside the other - intersection found */
+ distance= 0;
+ goto exit;
+ }
+ }
+
+ if (!cur_point)
+ continue;
+
+count_distance:
+ if (cur_point->shape >= obj2_si)
+ continue;
+ cur_point_edge= !cur_point->is_bottom();
+
+ for (dist_point= collector.get_first(); dist_point; dist_point= dist_point->get_next())
+ {
+ /* We only check vertices of object 2 */
+ if (dist_point->shape < obj2_si)
+ continue;
+
+ /* if we have an edge to check */
+ if (dist_point->left)
+ {
+ t= count_edge_t(dist_point, dist_point->left, cur_point,
+ ex, ey, vx, vy, e_sqrlen);
+ if ((t>0.0) && (t<1.0))
+ {
+ cur_distance= distance_to_line(ex, ey, vx, vy, e_sqrlen);
+ if (distance > cur_distance)
+ distance= cur_distance;
+ }
+ }
+ if (cur_point_edge)
+ {
+ t= count_edge_t(cur_point, cur_point->left, dist_point,
+ ex, ey, vx, vy, e_sqrlen);
+ if ((t>0.0) && (t<1.0))
+ {
+ cur_distance= distance_to_line(ex, ey, vx, vy, e_sqrlen);
+ if (distance > cur_distance)
+ distance= cur_distance;
+ }
+ }
+ cur_distance= distance_points(cur_point, dist_point);
+ if (distance > cur_distance)
+ distance= cur_distance;
+ }
+ }
+exit:
+ collector.reset();
+ func.reset();
+ scan_it.reset();
+ DBUG_RETURN(distance);
+mem_error:
+ null_value= 1;
+ DBUG_RETURN(0);
+}
+
+
#endif /*HAVE_SPATIAL*/
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index c5c1eae2d39..3638d9f62e8 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -1,7 +1,8 @@
#ifndef ITEM_GEOFUNC_INCLUDED
#define ITEM_GEOFUNC_INCLUDED
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates.
+ Copyright (C) 2011 Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,8 +14,8 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ along with this program; if not, write to the Free Software Foundation,
+ 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
/* This file defines all spatial functions */
@@ -25,6 +26,9 @@
#pragma interface /* gcc class implementation */
#endif
+#include "gcalc_slicescan.h"
+#include "gcalc_tools.h"
+
class Item_geometry_func: public Item_str_func
{
public:
@@ -44,7 +48,7 @@ class Item_func_geometry_from_text: public Item_geometry_func
public:
Item_func_geometry_from_text(Item *a) :Item_geometry_func(a) {}
Item_func_geometry_from_text(Item *a, Item *srid) :Item_geometry_func(a, srid) {}
- const char *func_name() const { return "geometryfromtext"; }
+ const char *func_name() const { return "st_geometryfromtext"; }
String *val_str(String *);
};
@@ -53,7 +57,7 @@ class Item_func_geometry_from_wkb: public Item_geometry_func
public:
Item_func_geometry_from_wkb(Item *a): Item_geometry_func(a) {}
Item_func_geometry_from_wkb(Item *a, Item *srid): Item_geometry_func(a, srid) {}
- const char *func_name() const { return "geometryfromwkb"; }
+ const char *func_name() const { return "st_geometryfromwkb"; }
String *val_str(String *);
};
@@ -61,7 +65,7 @@ class Item_func_as_wkt: public Item_str_ascii_func
{
public:
Item_func_as_wkt(Item *a): Item_str_ascii_func(a) {}
- const char *func_name() const { return "astext"; }
+ const char *func_name() const { return "st_astext"; }
String *val_str_ascii(String *);
void fix_length_and_dec();
};
@@ -70,7 +74,7 @@ class Item_func_as_wkb: public Item_geometry_func
{
public:
Item_func_as_wkb(Item *a): Item_geometry_func(a) {}
- const char *func_name() const { return "aswkb"; }
+ const char *func_name() const { return "st_aswkb"; }
String *val_str(String *);
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
};
@@ -80,7 +84,7 @@ class Item_func_geometry_type: public Item_str_ascii_func
public:
Item_func_geometry_type(Item *a): Item_str_ascii_func(a) {}
String *val_str_ascii(String *);
- const char *func_name() const { return "geometrytype"; }
+ const char *func_name() const { return "st_geometrytype"; }
void fix_length_and_dec()
{
// "GeometryCollection" is the longest
@@ -93,7 +97,7 @@ class Item_func_centroid: public Item_geometry_func
{
public:
Item_func_centroid(Item *a): Item_geometry_func(a) {}
- const char *func_name() const { return "centroid"; }
+ const char *func_name() const { return "st_centroid"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
};
@@ -102,7 +106,7 @@ class Item_func_envelope: public Item_geometry_func
{
public:
Item_func_envelope(Item *a): Item_geometry_func(a) {}
- const char *func_name() const { return "envelope"; }
+ const char *func_name() const { return "st_envelope"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
};
@@ -112,7 +116,7 @@ class Item_func_point: public Item_geometry_func
public:
Item_func_point(Item *a, Item *b): Item_geometry_func(a, b) {}
Item_func_point(Item *a, Item *b, Item *srid): Item_geometry_func(a, b, srid) {}
- const char *func_name() const { return "point"; }
+ const char *func_name() const { return "st_point"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
};
@@ -128,11 +132,11 @@ public:
switch (decomp_func)
{
case SP_STARTPOINT:
- return "startpoint";
+ return "st_startpoint";
case SP_ENDPOINT:
- return "endpoint";
+ return "st_endpoint";
case SP_EXTERIORRING:
- return "exteriorring";
+ return "st_exteriorring";
default:
DBUG_ASSERT(0); // Should never happened
return "spatial_decomp_unknown";
@@ -152,11 +156,11 @@ public:
switch (decomp_func_n)
{
case SP_POINTN:
- return "pointn";
+ return "st_pointn";
case SP_GEOMETRYN:
- return "geometryn";
+ return "st_geometryn";
case SP_INTERIORRINGN:
- return "interiorringn";
+ return "st_interiorringn";
default:
DBUG_ASSERT(0); // Should never happened
return "spatial_decomp_n_unknown";
@@ -195,57 +199,53 @@ public:
}
}
- const char *func_name() const { return "multipoint"; }
+ const char *func_name() const { return "st_multipoint"; }
};
+
/*
Spatial relations
*/
-class Item_func_spatial_rel: public Item_bool_func2
+class Item_func_spatial_mbr_rel: public Item_bool_func2
{
enum Functype spatial_rel;
public:
- Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel) :
+ Item_func_spatial_mbr_rel(Item *a,Item *b, enum Functype sp_rel) :
Item_bool_func2(a,b) { spatial_rel = sp_rel; }
longlong val_int();
enum Functype functype() const
{
- switch (spatial_rel) {
- case SP_CONTAINS_FUNC:
- return SP_WITHIN_FUNC;
- case SP_WITHIN_FUNC:
- return SP_CONTAINS_FUNC;
- default:
- return spatial_rel;
- }
+ return spatial_rel;
}
enum Functype rev_functype() const { return spatial_rel; }
- const char *func_name() const
- {
- switch (spatial_rel) {
- case SP_CONTAINS_FUNC:
- return "contains";
- case SP_WITHIN_FUNC:
- return "within";
- case SP_EQUALS_FUNC:
- return "equals";
- case SP_DISJOINT_FUNC:
- return "disjoint";
- case SP_INTERSECTS_FUNC:
- return "intersects";
- case SP_TOUCHES_FUNC:
- return "touches";
- case SP_CROSSES_FUNC:
- return "crosses";
- case SP_OVERLAPS_FUNC:
- return "overlaps";
- default:
- DBUG_ASSERT(0); // Should never happened
- return "sp_unknown";
- }
+ const char *func_name() const;
+ virtual inline void print(String *str, enum_query_type query_type)
+ {
+ Item_func::print(str, query_type);
}
+ void fix_length_and_dec() { maybe_null= 1; }
+ bool is_null() { (void) val_int(); return null_value; }
+};
+
+class Item_func_spatial_rel: public Item_bool_func2
+{
+ enum Functype spatial_rel;
+ Gcalc_heap collector;
+ Gcalc_scan_iterator scan_it;
+ Gcalc_function func;
+ String tmp_value1,tmp_value2;
+public:
+ Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel);
+ virtual ~Item_func_spatial_rel();
+ longlong val_int();
+ enum Functype functype() const
+ {
+ return spatial_rel;
+ }
+ enum Functype rev_functype() const { return spatial_rel; }
+ const char *func_name() const;
virtual inline void print(String *str, enum_query_type query_type)
{
Item_func::print(str, query_type);
@@ -255,23 +255,107 @@ public:
bool is_null() { (void) val_int(); return null_value; }
};
+
+/*
+ Spatial operations
+*/
+
+class Item_func_spatial_operation: public Item_geometry_func
+{
+public:
+ Gcalc_function::op_type spatial_op;
+ Gcalc_heap collector;
+ Gcalc_function func;
+
+ Gcalc_result_receiver res_receiver;
+ Gcalc_operation_reducer operation;
+ String tmp_value1,tmp_value2;
+public:
+ Item_func_spatial_operation(Item *a,Item *b, Gcalc_function::op_type sp_op) :
+ Item_geometry_func(a, b), spatial_op(sp_op)
+ {}
+ virtual ~Item_func_spatial_operation();
+ String *val_str(String *);
+ const char *func_name() const;
+ virtual inline void print(String *str, enum_query_type query_type)
+ {
+ Item_func::print(str, query_type);
+ }
+};
+
+
+class Item_func_buffer: public Item_geometry_func
+{
+protected:
+ class Transporter : public Gcalc_operation_transporter
+ {
+ int m_npoints;
+ double m_d;
+ double x1,y1,x2,y2;
+ double x00,y00,x01,y01;
+ int add_edge_buffer(double x3, double y3, bool round_p1, bool round_p2);
+ int add_last_edge_buffer();
+ int add_point_buffer(double x, double y);
+ int complete();
+ int m_nshapes;
+ Gcalc_function::op_type buffer_op;
+ int last_shape_pos;
+ bool skip_line;
+
+ public:
+ Transporter(Gcalc_function *fn, Gcalc_heap *heap, double d) :
+ Gcalc_operation_transporter(fn, heap), m_npoints(0), m_d(d),
+ m_nshapes(0), buffer_op((d > 0.0) ? Gcalc_function::op_union :
+ Gcalc_function::op_difference),
+ skip_line(FALSE)
+ {}
+ int single_point(double x, double y);
+ int start_line();
+ int complete_line();
+ int start_poly();
+ int complete_poly();
+ int start_ring();
+ int complete_ring();
+ int add_point(double x, double y);
+
+ int start_collection(int n_objects);
+ };
+ Gcalc_heap collector;
+ Gcalc_function func;
+
+ Gcalc_result_receiver res_receiver;
+ Gcalc_operation_reducer operation;
+ String tmp_value;
+
+public:
+ Item_func_buffer(Item *obj, Item *distance):
+ Item_geometry_func(obj, distance) {}
+ const char *func_name() const { return "st_buffer"; }
+ String *val_str(String *);
+};
+
+
class Item_func_isempty: public Item_bool_func
{
public:
Item_func_isempty(Item *a): Item_bool_func(a) {}
longlong val_int();
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
- const char *func_name() const { return "isempty"; }
+ const char *func_name() const { return "st_isempty"; }
void fix_length_and_dec() { maybe_null= 1; }
};
class Item_func_issimple: public Item_bool_func
{
+ Gcalc_heap collector;
+ Gcalc_function func;
+ Gcalc_scan_iterator scan_it;
+ String tmp;
public:
Item_func_issimple(Item *a): Item_bool_func(a) {}
longlong val_int();
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
- const char *func_name() const { return "issimple"; }
+ const char *func_name() const { return "st_issimple"; }
void fix_length_and_dec() { maybe_null= 1; }
};
@@ -281,7 +365,7 @@ public:
Item_func_isclosed(Item *a): Item_bool_func(a) {}
longlong val_int();
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
- const char *func_name() const { return "isclosed"; }
+ const char *func_name() const { return "st_isclosed"; }
void fix_length_and_dec() { maybe_null= 1; }
};
@@ -291,7 +375,7 @@ class Item_func_dimension: public Item_int_func
public:
Item_func_dimension(Item *a): Item_int_func(a) {}
longlong val_int();
- const char *func_name() const { return "dimension"; }
+ const char *func_name() const { return "st_dimension"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
@@ -301,7 +385,7 @@ class Item_func_x: public Item_real_func
public:
Item_func_x(Item *a): Item_real_func(a) {}
double val_real();
- const char *func_name() const { return "x"; }
+ const char *func_name() const { return "st_x"; }
void fix_length_and_dec()
{
Item_real_func::fix_length_and_dec();
@@ -316,7 +400,7 @@ class Item_func_y: public Item_real_func
public:
Item_func_y(Item *a): Item_real_func(a) {}
double val_real();
- const char *func_name() const { return "y"; }
+ const char *func_name() const { return "st_y"; }
void fix_length_and_dec()
{
Item_real_func::fix_length_and_dec();
@@ -331,7 +415,7 @@ class Item_func_numgeometries: public Item_int_func
public:
Item_func_numgeometries(Item *a): Item_int_func(a) {}
longlong val_int();
- const char *func_name() const { return "numgeometries"; }
+ const char *func_name() const { return "st_numgeometries"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
@@ -342,7 +426,7 @@ class Item_func_numinteriorring: public Item_int_func
public:
Item_func_numinteriorring(Item *a): Item_int_func(a) {}
longlong val_int();
- const char *func_name() const { return "numinteriorrings"; }
+ const char *func_name() const { return "st_numinteriorrings"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
@@ -353,7 +437,7 @@ class Item_func_numpoints: public Item_int_func
public:
Item_func_numpoints(Item *a): Item_int_func(a) {}
longlong val_int();
- const char *func_name() const { return "numpoints"; }
+ const char *func_name() const { return "st_numpoints"; }
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
@@ -364,7 +448,7 @@ class Item_func_area: public Item_real_func
public:
Item_func_area(Item *a): Item_real_func(a) {}
double val_real();
- const char *func_name() const { return "area"; }
+ const char *func_name() const { return "st_area"; }
void fix_length_and_dec()
{
Item_real_func::fix_length_and_dec();
@@ -379,7 +463,7 @@ class Item_func_glength: public Item_real_func
public:
Item_func_glength(Item *a): Item_real_func(a) {}
double val_real();
- const char *func_name() const { return "glength"; }
+ const char *func_name() const { return "st_length"; }
void fix_length_and_dec()
{
Item_real_func::fix_length_and_dec();
@@ -398,12 +482,25 @@ public:
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
};
+
+class Item_func_distance: public Item_real_func
+{
+ String tmp_value1;
+ String tmp_value2;
+ Gcalc_heap collector;
+ Gcalc_function func;
+ Gcalc_scan_iterator scan_it;
+public:
+ Item_func_distance(Item *a, Item *b): Item_real_func(a, b) {}
+ double val_real();
+ const char *func_name() const { return "st_distance"; }
+};
+
#define GEOM_NEW(thd, obj_constructor) new (thd->mem_root) obj_constructor
#else /*HAVE_SPATIAL*/
#define GEOM_NEW(thd, obj_constructor) NULL
-#endif
-
+#endif /*HAVE_SPATIAL*/
#endif /* ITEM_GEOFUNC_INCLUDED */
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 2a922541f72..c6e1bf584e3 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1236,13 +1236,13 @@ int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param,
if (result)
{
+ result->keys_map= result_keys;
if (result_keys.is_clear_all())
result->type= SEL_TREE::ALWAYS;
if ((result->type == SEL_TREE::MAYBE) ||
(result->type == SEL_TREE::ALWAYS))
return 1;
/* SEL_TREE::IMPOSSIBLE is impossible here */
- result->keys_map= result_keys;
*or_tree= result;
was_ored= TRUE;
}
@@ -8656,8 +8656,8 @@ key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2, uint clone_flag)
continue;
SEL_ARG *next=key_and(param, e1->next_key_part, e2->next_key_part,
clone_flag);
- e1->increment_use_count(1);
- e2->increment_use_count(1);
+ e1->incr_refs();
+ e2->incr_refs();
if (!next || next->type != SEL_ARG::IMPOSSIBLE)
{
SEL_ARG *new_arg= e1->clone_and(e2);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 0aa6fb7e913..02a57a9e7df 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -446,7 +446,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
subquery execution strategies based on optimizer switches and syntactic
properties.
*/
- if (in_subs)
+ if (in_subs && !in_subs->has_strategy())
{
if (is_materialization_applicable(thd, in_subs, select_lex))
{
@@ -3920,8 +3920,8 @@ int setup_semijoin_dups_elimination(JOIN *join, ulonglong options,
if (j != join->const_tables && js_tab->use_quick != 2 &&
j <= no_jbuf_after &&
((js_tab->type == JT_ALL && join_cache_level != 0) ||
- (join_cache_level > 2 && (tab->type == JT_REF ||
- tab->type == JT_EQ_REF))))
+ (join_cache_level > 2 && (js_tab->type == JT_REF ||
+ js_tab->type == JT_EQ_REF))))
{
/* Looks like we'll be using join buffer */
first_table= join->const_tables;
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index 5a7416fe929..08af798948d 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -170,7 +170,7 @@ public:
PREV_BITS(ulonglong, s->emb_sj_nest->sj_in_exprs) && // (2)
(PREV_BITS(key_part_map, max_loose_keypart+1) & // (3)
(found_part | loose_scan_keyparts)) == // (3)
- (found_part | loose_scan_keyparts) && // (3)
+ PREV_BITS(key_part_map, max_loose_keypart+1) && // (3)
!key_uses_partial_cols(s->table, key))
{
/* Ok, can use the strategy */
diff --git a/sql/plistsort.c b/sql/plistsort.c
new file mode 100644
index 00000000000..71d287e7b45
--- /dev/null
+++ b/sql/plistsort.c
@@ -0,0 +1,166 @@
+/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/*
+things to define before including the file:
+
+#define LS_LIST_ITEM ListItem
+#define LS_COMPARE_FUNC_DECL compare_func var_name,
+#define LS_COMPARE_FUNC_CALL(list_el1, list_el2) (*var_name)(list_el1, list_el2)
+#define LS_NEXT(A) (A)->next
+#define LS_SET_NEXT(A,val) (A)->next= val
+#define LS_P_NEXT(A) &(A)->next
+#define LS_NAME plistsort
+#define LS_SCOPE static
+#define LS_STRUCT_NAME ls_struct_name
+*/
+
+typedef struct LS_STRUCT_NAME
+{
+ LS_LIST_ITEM *list1;
+ int list_len;
+ int return_point;
+} LS_STRUCT_NAME;
+
+LS_SCOPE LS_LIST_ITEM* LS_NAME(LS_COMPARE_FUNC_DECL LS_LIST_ITEM *list, int list_len)
+{
+ LS_LIST_ITEM *list_end;
+ LS_LIST_ITEM *sorted_list;
+
+ struct LS_STRUCT_NAME stack[63], *sp= stack;
+
+ if (list_len < 2)
+ return list;
+
+ sp->list_len= list_len;
+ sp->return_point= 2;
+
+recursion_point:
+
+ if (sp->list_len < 4)
+ {
+ LS_LIST_ITEM *e1, *e2;
+ sorted_list= list;
+ e1= LS_NEXT(sorted_list);
+ list_end= LS_NEXT(e1);
+ if (LS_COMPARE_FUNC_CALL(sorted_list, e1))
+ {
+ sorted_list= e1;
+ e1= list;
+ }
+ if (sp->list_len == 2)
+ {
+ LS_SET_NEXT(sorted_list, e1);
+ LS_SET_NEXT(e1, NULL);
+ goto exit_point;
+ }
+ e2= list_end;
+ list_end= LS_NEXT(e2);
+ if (LS_COMPARE_FUNC_CALL(e1, e2))
+ {
+ {
+ LS_LIST_ITEM *tmp_e= e1;
+ e1= e2;
+ e2= tmp_e;
+ }
+ if (LS_COMPARE_FUNC_CALL(sorted_list, e1))
+ {
+ LS_LIST_ITEM *tmp_e= sorted_list;
+ sorted_list= e1;
+ e1= tmp_e;
+ }
+ }
+
+ LS_SET_NEXT(sorted_list, e1);
+ LS_SET_NEXT(e1, e2);
+ LS_SET_NEXT(e2, NULL);
+ goto exit_point;
+ }
+
+ {
+ register struct LS_STRUCT_NAME *sp0= sp++;
+ sp->list_len= sp0->list_len >> 1;
+ sp0->list_len-= sp->list_len;
+ sp->return_point= 0;
+ }
+ goto recursion_point;
+return_point0:
+ sp->list1= sorted_list;
+ {
+ register struct LS_STRUCT_NAME *sp0= sp++;
+ list= list_end;
+ sp->list_len= sp0->list_len;
+ sp->return_point= 1;
+ }
+ goto recursion_point;
+return_point1:
+ {
+ register LS_LIST_ITEM **hook= &sorted_list;
+ register LS_LIST_ITEM *list1= sp->list1;
+ register LS_LIST_ITEM *list2= sorted_list;
+
+ if (LS_COMPARE_FUNC_CALL(list1, list2))
+ {
+ LS_LIST_ITEM *tmp_e= list2;
+ list2= list1;
+ list1= tmp_e;
+ }
+ for (;;)
+ {
+ *hook= list1;
+ do
+ {
+ if (!(list1= *(hook= LS_P_NEXT(list1))))
+ {
+ *hook= list2;
+ goto exit_point;
+ }
+ } while (LS_COMPARE_FUNC_CALL(list2, list1));
+
+ *hook= list2;
+ do
+ {
+ if (!(list2= *(hook= LS_P_NEXT(list2))))
+ {
+ *hook= list1;
+ goto exit_point;
+ }
+ } while (LS_COMPARE_FUNC_CALL(list1, list2));
+ }
+ }
+
+exit_point:
+ switch ((sp--)->return_point)
+ {
+ case 0: goto return_point0;
+ case 1: goto return_point1;
+ default:;
+ }
+
+ return sorted_list;
+}
+
+
+#undef LS_LIST_ITEM
+#undef LS_NEXT
+#undef LS_SET_NEXT
+#undef LS_P_NEXT
+#undef LS_NAME
+#undef LS_STRUCT_NAME
+#undef LS_SCOPE
+#undef LS_COMPARE_FUNC_DECL
+#undef LS_COMPARE_FUNC_CALL
+
diff --git a/sql/spatial.cc b/sql/spatial.cc
index ee701d82657..4dfc20716fc 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -1,5 +1,6 @@
/*
- Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2002, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2011, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -22,6 +23,27 @@
#ifdef HAVE_SPATIAL
+/*
+ exponential notation :
+ 1 sign
+ 1 number before the decimal point
+ 1 decimal point
+ 14 number of significant digits (see String::qs_append(double))
+ 1 'e' sign
+ 1 exponent sign
+ 3 exponent digits
+ ==
+ 22
+
+ "f" notation :
+ 1 optional 0
+ 1 sign
+ 14 number significant digits (see String::qs_append(double) )
+ 1 decimal point
+ ==
+ 17
+*/
+
#define MAX_DIGITS_IN_DOUBLE MY_GCVT_MAX_FIELD_WIDTH
/***************************** Gis_class_info *******************************/
@@ -162,6 +184,7 @@ Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer,
{
LEX_STRING name;
Class_info *ci;
+ char next_sym;
if (trs->get_next_word(&name))
{
@@ -174,9 +197,13 @@ Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer,
Geometry *result= (*ci->m_create_func)(buffer->data);
wkt->q_append((char) wkb_ndr);
wkt->q_append((uint32) result->get_class_info()->m_type_id);
- if (trs->check_next_symbol('(') ||
+ if (!(next_sym= trs->next_symbol()))
+ return NULL;
+ if (!(next_sym= trs->next_symbol()))
+ return NULL;
+ if ((next_sym == '(' && trs->check_next_symbol('(')) ||
result->init_from_wkt(trs, wkt) ||
- trs->check_next_symbol(')'))
+ (next_sym == '(' && trs->check_next_symbol(')')))
return NULL;
if (init_stream)
{
@@ -187,6 +214,22 @@ Geometry *Geometry::create_from_wkt(Geometry_buffer *buffer,
}
+int Geometry::as_wkt(String *wkt, const char **end)
+{
+ uint32 len= (uint) get_class_info()->m_name.length;
+ if (wkt->reserve(len + 2, 512))
+ return 1;
+ wkt->qs_append(get_class_info()->m_name.str, len);
+ if (get_class_info() != &geometrycollection_class)
+ wkt->qs_append('(');
+ if (get_data_as_wkt(wkt, end))
+ return 1;
+ if (get_class_info() != &geometrycollection_class)
+ wkt->qs_append(')');
+ return 0;
+}
+
+
static double wkb_get_double(const char *ptr, Geometry::wkbByteOrder bo)
{
double res;
@@ -248,12 +291,37 @@ Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer,
}
+int Geometry::create_from_opresult(Geometry_buffer *g_buf,
+ String *res, Gcalc_result_receiver &rr)
+{
+ uint32 geom_type= rr.get_result_typeid();
+ Geometry *obj= create_by_typeid(g_buf, geom_type);
+
+ if (!obj || res->reserve(WKB_HEADER_SIZE, 512))
+ return 1;
+
+ res->q_append((char) wkb_ndr);
+ res->q_append(geom_type);
+ return obj->init_from_opresult(res, rr.result(), rr.length());
+}
+
+
bool Geometry::envelope(String *result) const
{
MBR mbr;
const char *end;
- if (get_mbr(&mbr, &end) || result->reserve(1+4*3+SIZEOF_STORED_DOUBLE*10))
+ if (get_mbr(&mbr, &end))
+ {
+ /* Empty geometry */
+ if (result->reserve(1 + 4*2))
+ return 1;
+ result->q_append((char) wkb_ndr);
+ result->q_append((uint32) wkb_geometrycollection);
+ result->q_append((uint32) 0);
+ return 0;
+ }
+ if (result->reserve(1 + 4 * 3 + SIZEOF_STORED_DOUBLE * 10))
return 1;
result->q_append((char) wkb_ndr);
@@ -290,13 +358,13 @@ bool Geometry::envelope(String *result) const
bool Geometry::create_point(String *result, const char *data) const
{
- if (no_data(data, SIZEOF_STORED_DOUBLE * 2) ||
- result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
+ if (no_data(data, POINT_DATA_SIZE) ||
+ result->reserve(1 + 4 + POINT_DATA_SIZE))
return 1;
result->q_append((char) wkb_ndr);
result->q_append((uint32) wkb_point);
/* Copy two double in same format */
- result->q_append(data, SIZEOF_STORED_DOUBLE*2);
+ result->q_append(data, POINT_DATA_SIZE);
return 0;
}
@@ -316,7 +384,7 @@ bool Geometry::create_point(String *result, const char *data) const
bool Geometry::create_point(String *result, double x, double y) const
{
- if (result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
+ if (result->reserve(1 + 4 + POINT_DATA_SIZE))
return 1;
result->q_append((char) wkb_ndr);
@@ -348,7 +416,7 @@ const char *Geometry::append_points(String *txt, uint32 n_points,
double x,y;
data+= offset;
get_point(&x, &y, data);
- data+= SIZEOF_STORED_DOUBLE * 2;
+ data+= POINT_DATA_SIZE;
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
@@ -383,7 +451,7 @@ const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
points= uint4korr(data);
data+= 4;
- if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points))
+ if (no_data(data, (POINT_DATA_SIZE + offset) * points))
return 0;
/* Calculate MBR for points */
@@ -391,7 +459,7 @@ const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
{
data+= offset;
mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE);
- data+= SIZEOF_STORED_DOUBLE * 2;
+ data+= POINT_DATA_SIZE;
}
return data;
}
@@ -409,7 +477,7 @@ bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
double x, y;
if (trs->get_next_number(&x) || trs->get_next_number(&y) ||
- wkb->reserve(SIZEOF_STORED_DOUBLE * 2))
+ wkb->reserve(POINT_DATA_SIZE))
return 1;
wkb->q_append(x);
wkb->q_append(y);
@@ -456,6 +524,31 @@ bool Gis_point::get_mbr(MBR *mbr, const char **end) const
return 0;
}
+
+int Gis_point::area(double *ar, const char **end) const
+{
+ *ar= 0;
+ *end= m_data+ POINT_DATA_SIZE;
+ return 0;
+}
+
+
+int Gis_point::geom_length(double *len, const char **end) const
+{
+ *len= 0;
+ *end= m_data+ POINT_DATA_SIZE;
+ return 0;
+}
+
+
+int Gis_point::store_shapes(Gcalc_shape_transporter *trn) const
+{
+ double x, y;
+
+ return get_xy(&x, &y) || trn->single_point(x, y);
+}
+
+
const Geometry::Class_info *Gis_point::get_class_info() const
{
return &point_class;
@@ -507,12 +600,12 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len,
const char *wkb_end;
Gis_point p;
- if (len < 4)
+ if (len < 4 ||
+ (n_points= wkb_get_uint(wkb, bo))<1)
return 0;
- n_points= wkb_get_uint(wkb, bo);
proper_length= 4 + n_points * POINT_DATA_SIZE;
- if (!n_points || len < proper_length || res->reserve(proper_length))
+ if (len < proper_length || res->reserve(proper_length))
return 0;
res->q_append(n_points);
@@ -538,7 +631,7 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const
data += 4;
if (n_points < 1 ||
- no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) ||
+ no_data(data, POINT_DATA_SIZE * n_points) ||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
return 1;
@@ -546,7 +639,7 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const
{
double x, y;
get_point(&x, &y, data);
- data+= SIZEOF_STORED_DOUBLE * 2;
+ data+= POINT_DATA_SIZE;
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
@@ -564,7 +657,7 @@ bool Gis_line_string::get_mbr(MBR *mbr, const char **end) const
}
-int Gis_line_string::geom_length(double *len) const
+int Gis_line_string::geom_length(double *len, const char **end) const
{
uint32 n_points;
double prev_x, prev_y;
@@ -575,21 +668,35 @@ int Gis_line_string::geom_length(double *len) const
return 1;
n_points= uint4korr(data);
data+= 4;
- if (n_points < 1 || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
+ if (n_points < 1 || no_data(data, POINT_DATA_SIZE * n_points))
return 1;
get_point(&prev_x, &prev_y, data);
- data+= SIZEOF_STORED_DOUBLE*2;
-
+ data+= POINT_DATA_SIZE;
while (--n_points)
{
double x, y;
get_point(&x, &y, data);
- data+= SIZEOF_STORED_DOUBLE * 2;
+ data+= POINT_DATA_SIZE;
*len+= sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
prev_x= x;
prev_y= y;
}
+ *end= data;
+ return 0;
+}
+
+
+int Gis_line_string::area(double *ar, const char **end) const
+{
+ uint32 n_points;
+ *ar= 0.0;
+
+ /* read number of points */
+ if (no_data(m_data, 4))
+ return 1;
+ n_points= uint4korr(m_data);
+ *end= m_data + 4 + POINT_DATA_SIZE * n_points;
return 0;
}
@@ -609,14 +716,14 @@ int Gis_line_string::is_closed(int *closed) const
return 0;
}
data+= 4;
- if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
+ if (no_data(data, POINT_DATA_SIZE * n_points))
return 1;
/* Get first point */
get_point(&x1, &y1, data);
/* get last point */
- data+= SIZEOF_STORED_DOUBLE*2 + (n_points-2)*POINT_DATA_SIZE;
+ data+= POINT_DATA_SIZE + (n_points-2)*POINT_DATA_SIZE;
get_point(&x2, &y2, data);
*closed= (x1==x2) && (y1==y2);
@@ -660,6 +767,41 @@ int Gis_line_string::point_n(uint32 num, String *result) const
return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE);
}
+
+int Gis_line_string::store_shapes(Gcalc_shape_transporter *trn) const
+{
+ uint32 n_points;
+ double x, y;
+ double UNINIT_VAR(prev_x), UNINIT_VAR(prev_y);
+ int first_point= 1;
+ const char *data= m_data;
+
+ if (no_data(m_data, 4))
+ return 1;
+ n_points= uint4korr(data);
+ data+= 4;
+ if (n_points < 1 || no_data(data, POINT_DATA_SIZE * n_points))
+ return 1;
+
+ trn->start_line();
+
+ while (n_points--)
+ {
+ get_point(&x, &y, data);
+ data+= POINT_DATA_SIZE;
+ if (!first_point && x == prev_x && y == prev_y)
+ continue;
+ if (trn->add_point(x, y))
+ return 1;
+ first_point= 0;
+ prev_x= x;
+ prev_y= y;
+ }
+
+ return trn->complete_line();
+}
+
+
const Geometry::Class_info *Gis_line_string::get_class_info() const
{
return &linestring_class;
@@ -721,6 +863,52 @@ bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
}
+uint Gis_polygon::init_from_opresult(String *bin,
+ const char *opres, uint res_len)
+{
+ const char *opres_orig= opres;
+ uint32 position= bin->length();
+ uint32 poly_shapes= 0;
+
+ if (bin->reserve(4, 512))
+ return 0;
+ bin->q_append(poly_shapes);
+
+ while (opres_orig + res_len > opres)
+ {
+ uint32 n_points, proper_length;
+ const char *op_end, *p1_position;
+ Gis_point p;
+ Gcalc_function::shape_type st;
+
+ st= (Gcalc_function::shape_type) uint4korr(opres);
+ if (poly_shapes && st != Gcalc_function::shape_hole)
+ break;
+ poly_shapes++;
+ n_points= uint4korr(opres + 4) + 1; /* skip shape type id */
+ proper_length= 4 + n_points * POINT_DATA_SIZE;
+
+ if (bin->reserve(proper_length, 512))
+ return 0;
+
+ bin->q_append(n_points);
+ op_end= opres + 8 + (n_points-1) * 8 * 2;
+ p1_position= (opres+= 8);
+ for (; opres<op_end; opres+= POINT_DATA_SIZE)
+ {
+ if (!p.init_from_wkb(opres, POINT_DATA_SIZE, wkb_ndr, bin))
+ return 0;
+ }
+ if (!p.init_from_wkb(p1_position, POINT_DATA_SIZE, wkb_ndr, bin))
+ return 0;
+ }
+
+ bin->write_at_position(position, poly_shapes);
+
+ return (uint) (opres - opres_orig);
+}
+
+
uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
String *res)
{
@@ -730,9 +918,7 @@ uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
if (len < 4)
return 0;
- if (!(n_linear_rings= wkb_get_uint(wkb, bo)))
- return 0;
-
+ n_linear_rings= wkb_get_uint(wkb, bo);
if (res->reserve(4, 512))
return 0;
wkb+= 4;
@@ -778,7 +964,7 @@ bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const
return 1;
n_points= uint4korr(data);
data+= 4;
- if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
+ if (no_data(data, POINT_DATA_SIZE * n_points) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
@@ -832,16 +1018,16 @@ int Gis_polygon::area(double *ar, const char **end_of_data) const
if (no_data(data, 4))
return 1;
n_points= uint4korr(data);
- if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
+ if (no_data(data, POINT_DATA_SIZE * n_points))
return 1;
get_point(&prev_x, &prev_y, data+4);
- data+= (4+SIZEOF_STORED_DOUBLE*2);
+ data+= (4+POINT_DATA_SIZE);
while (--n_points) // One point is already read
{
double x, y;
get_point(&x, &y, data);
- data+= (SIZEOF_STORED_DOUBLE*2);
+ data+= POINT_DATA_SIZE;
lr_area+= (prev_x + x)* (prev_y - y);
prev_x= x;
prev_y= y;
@@ -868,7 +1054,7 @@ int Gis_polygon::exterior_ring(String *result) const
n_points= uint4korr(data);
data+= 4;
length= n_points * POINT_DATA_SIZE;
- if (no_data(data, length) || result->reserve(1+4+4+ length))
+ if (no_data(data, length) || result->reserve(1 + 4 + 4 + length))
return 1;
result->q_append((char) wkb_ndr);
@@ -914,7 +1100,7 @@ int Gis_polygon::interior_ring_n(uint32 num, String *result) const
n_points= uint4korr(data);
points_size= n_points * POINT_DATA_SIZE;
data+= 4;
- if (no_data(data, points_size) || result->reserve(1+4+4+ points_size))
+ if (no_data(data, points_size) || result->reserve(1 + 4 + 4 + points_size))
return 1;
result->q_append((char) wkb_ndr);
@@ -953,16 +1139,16 @@ int Gis_polygon::centroid_xy(double *x, double *y) const
return 1;
org_n_points= n_points= uint4korr(data);
data+= 4;
- if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
+ if (no_data(data, POINT_DATA_SIZE * n_points))
return 1;
get_point(&prev_x, &prev_y, data);
- data+= (SIZEOF_STORED_DOUBLE*2);
+ data+= POINT_DATA_SIZE;
while (--n_points) // One point is already read
{
double tmp_x, tmp_y;
get_point(&tmp_x, &tmp_y, data);
- data+= (SIZEOF_STORED_DOUBLE*2);
+ data+= POINT_DATA_SIZE;
cur_area+= (prev_x + tmp_x) * (prev_y - tmp_y);
cur_cx+= tmp_x;
cur_cy+= tmp_y;
@@ -1002,6 +1188,74 @@ int Gis_polygon::centroid(String *result) const
return create_point(result, x, y);
}
+
+int Gis_polygon::store_shapes(Gcalc_shape_transporter *trn) const
+{
+ uint32 n_linear_rings;
+ const char *data= m_data;
+ double first_x, first_y;
+ double prev_x, prev_y;
+ int was_equal_first= 0;
+
+ if (trn->start_poly())
+ return 1;
+
+ if (no_data(data, 4))
+ return 1;
+ n_linear_rings= uint4korr(data);
+ data+= 4;
+
+ while (n_linear_rings--)
+ {
+ uint32 n_points;
+
+ if (no_data(data, 4))
+ return 1;
+ n_points= uint4korr(data);
+ data+= 4;
+ if (!n_points || no_data(data, POINT_DATA_SIZE * n_points))
+ return 1;
+
+ trn->start_ring();
+ get_point(&first_x, &first_y, data);
+ data+= POINT_DATA_SIZE;
+ n_points--;
+ prev_x= first_x;
+ prev_y= first_y;
+ if (trn->add_point(first_x, first_y))
+ return 1;
+ while (--n_points)
+ {
+ double x, y;
+ get_point(&x, &y, data);
+ data+= POINT_DATA_SIZE;
+ if (x == prev_x && y == prev_y)
+ continue;
+ prev_x= x;
+ prev_y= y;
+ if (was_equal_first)
+ {
+ if (trn->add_point(first_x, first_y))
+ return 1;
+ was_equal_first= 0;
+ }
+ if (x == first_x && y == first_y)
+ {
+ was_equal_first= 1;
+ continue;
+ }
+ if (trn->add_point(x, y))
+ return 1;
+ }
+ data+= POINT_DATA_SIZE;
+ trn->complete_ring();
+ }
+
+ trn->complete_poly();
+ return 0;
+}
+
+
const Geometry::Class_info *Gis_polygon::get_class_info() const
{
return &polygon_class;
@@ -1030,7 +1284,7 @@ bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
for (;;)
{
- if (wkb->reserve(1+4, 512))
+ if (wkb->reserve(1 + 4, 512))
return 1;
wkb->q_append((char) wkb_ndr);
wkb->q_append((uint32) wkb_point);
@@ -1045,6 +1299,32 @@ bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
}
+uint Gis_multi_point::init_from_opresult(String *bin,
+ const char *opres, uint res_len)
+{
+ uint bin_size, n_points;
+ Gis_point p;
+ const char *opres_end;
+
+ n_points= res_len/(4+8*2);
+ bin_size= n_points * (WKB_HEADER_SIZE + POINT_DATA_SIZE) + 4;
+
+ if (bin->reserve(bin_size, 512))
+ return 0;
+
+ bin->q_append(n_points);
+ opres_end= opres + res_len;
+ for (; opres < opres_end; opres+= (4 + 8*2))
+ {
+ bin->q_append((char)wkb_ndr);
+ bin->q_append((uint32)wkb_point);
+ if (!p.init_from_wkb(opres + 4, POINT_DATA_SIZE, wkb_ndr, bin))
+ return 0;
+ }
+ return res_len;
+}
+
+
uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
String *res)
{
@@ -1083,7 +1363,7 @@ bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const
n_points= uint4korr(m_data);
if (no_data(m_data+4,
- n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) ||
+ n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE)) ||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
*end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE);
@@ -1124,6 +1404,35 @@ int Gis_multi_point::geometry_n(uint32 num, String *result) const
return 0;
}
+
+int Gis_multi_point::store_shapes(Gcalc_shape_transporter *trn) const
+{
+ uint32 n_points;
+ Gis_point pt;
+ const char *data= m_data;
+
+ if (no_data(data, 4))
+ return 1;
+ n_points= uint4korr(data);
+ data+= 4;
+
+ if (trn->start_collection(n_points))
+ return 1;
+
+ while (n_points--)
+ {
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ data+= WKB_HEADER_SIZE;
+ pt.set_data_ptr(data, (uint32) (m_data_end - data));
+ if (pt.store_shapes(trn))
+ return 1;
+ data+= pt.get_data_size();
+ }
+ return 0;
+}
+
+
const Geometry::Class_info *Gis_multi_point::get_class_info() const
{
return &multipoint_class;
@@ -1166,10 +1475,9 @@ bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
{
Gis_line_string ls;
- if (wkb->reserve(1+4, 512))
+ if (wkb->reserve(1 + 4, 512))
return 1;
- wkb->q_append((char) wkb_ndr);
- wkb->q_append((uint32) wkb_linestring);
+ wkb->q_append((char) wkb_ndr); wkb->q_append((uint32) wkb_linestring);
if (trs->check_next_symbol('(') ||
ls.init_from_wkt(trs, wkb) ||
@@ -1184,15 +1492,48 @@ bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
}
+uint Gis_multi_line_string::init_from_opresult(String *bin,
+ const char *opres, uint res_len)
+{
+ const char *opres_orig= opres;
+ int ns_pos= bin->length();
+ uint n_linestring= 0;
+
+ if (bin->reserve(4, 512))
+ return 0;
+ bin->q_append(n_linestring);
+
+ while (res_len)
+ {
+ Gis_line_string ls;
+ int ls_len;
+
+ if (bin->reserve(WKB_HEADER_SIZE, 512))
+ return 0;
+
+ bin->q_append((char) wkb_ndr);
+ bin->q_append((uint32) wkb_linestring);
+
+ if (!(ls_len= ls.init_from_opresult(bin, opres, res_len)))
+ return 0;
+ opres+= ls_len;
+ res_len-= ls_len;
+ n_linestring++;
+ }
+ bin->write_at_position(ns_pos, n_linestring);
+ return (uint) (opres - opres_orig);
+}
+
+
uint Gis_multi_line_string::init_from_wkb(const char *wkb, uint len,
wkbByteOrder bo, String *res)
{
uint32 n_line_strings;
const char *wkb_orig= wkb;
- if (len < 4)
+ if (len < 4 ||
+ (n_line_strings= wkb_get_uint(wkb, bo))< 1)
return 0;
- n_line_strings= wkb_get_uint(wkb, bo);
if (res->reserve(4, 512))
return 0;
@@ -1240,7 +1581,7 @@ bool Gis_multi_line_string::get_data_as_wkt(String *txt,
return 1;
n_points= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
- if (no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
+ if (no_data(data, n_points * POINT_DATA_SIZE) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
@@ -1311,10 +1652,11 @@ int Gis_multi_line_string::geometry_n(uint32 num, String *result) const
}
-int Gis_multi_line_string::geom_length(double *len) const
+int Gis_multi_line_string::geom_length(double *len, const char **end) const
{
uint32 n_line_strings;
const char *data= m_data;
+ const char *line_end;
if (no_data(data, 4))
return 1;
@@ -1328,7 +1670,7 @@ int Gis_multi_line_string::geom_length(double *len) const
Gis_line_string ls;
data+= WKB_HEADER_SIZE;
ls.set_data_ptr(data, (uint32) (m_data_end - data));
- if (ls.geom_length(&ls_len))
+ if (ls.geom_length(&ls_len, &line_end))
return 1;
*len+= ls_len;
/*
@@ -1337,6 +1679,7 @@ int Gis_multi_line_string::geom_length(double *len) const
*/
data+= ls.get_data_size();
}
+ *end= data;
return 0;
}
@@ -1370,6 +1713,35 @@ int Gis_multi_line_string::is_closed(int *closed) const
return 0;
}
+
+int Gis_multi_line_string::store_shapes(Gcalc_shape_transporter *trn) const
+{
+ uint32 n_lines;
+ Gis_line_string ls;
+ const char *data= m_data;
+
+ if (no_data(data, 4))
+ return 1;
+ n_lines= uint4korr(data);
+ data+= 4;
+
+ if (trn->start_collection(n_lines))
+ return 1;
+
+ while (n_lines--)
+ {
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ data+= WKB_HEADER_SIZE;
+ ls.set_data_ptr(data, (uint32) (m_data_end - data));
+ if (ls.store_shapes(trn))
+ return 1;
+ data+= ls.get_data_size();
+ }
+ return 0;
+}
+
+
const Geometry::Class_info *Gis_multi_line_string::get_class_info() const
{
return &multilinestring_class;
@@ -1420,7 +1792,7 @@ bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
for (;;)
{
- if (wkb->reserve(1+4, 512))
+ if (wkb->reserve(1 + 4, 512))
return 1;
wkb->q_append((char) wkb_ndr);
wkb->q_append((uint32) wkb_polygon);
@@ -1475,6 +1847,36 @@ uint Gis_multi_polygon::init_from_wkb(const char *wkb, uint len,
}
+uint Gis_multi_polygon::init_from_opresult(String *bin,
+ const char *opres, uint res_len)
+{
+ Gis_polygon p;
+ const char *opres_orig= opres;
+ uint p_len;
+ uint32 n_poly= 0;
+ uint32 np_pos= bin->length();
+
+ if (bin->reserve(4, 512))
+ return 0;
+
+ bin->q_append(n_poly);
+ while (res_len)
+ {
+ if (bin->reserve(1 + 4, 512))
+ return 0;
+ bin->q_append((char)wkb_ndr);
+ bin->q_append((uint32)wkb_polygon);
+ if (!(p_len= p.init_from_opresult(bin, opres, res_len)))
+ return 0;
+ opres+= p_len;
+ res_len-= p_len;
+ n_poly++;
+ }
+ bin->write_at_position(np_pos, n_poly);
+ return opres - opres_orig;
+}
+
+
bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const
{
uint32 n_polygons;
@@ -1501,7 +1903,7 @@ bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const
return 1;
uint32 n_points= uint4korr(data);
data+= 4;
- if (no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
+ if (no_data(data, POINT_DATA_SIZE * n_points) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
512))
return 1;
@@ -1654,6 +2056,35 @@ int Gis_multi_polygon::centroid(String *result) const
return create_point(result, res_cx, res_cy);
}
+
+int Gis_multi_polygon::store_shapes(Gcalc_shape_transporter *trn) const
+{
+ uint32 n_polygons;
+ Gis_polygon p;
+ const char *data= m_data;
+
+ if (no_data(data, 4))
+ return 1;
+ n_polygons= uint4korr(data);
+ data+= 4;
+
+ if (trn->start_collection(n_polygons))
+ return 1;
+
+ while (n_polygons--)
+ {
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ data+= WKB_HEADER_SIZE;
+ p.set_data_ptr(data, (uint32) (m_data_end - data));
+ if (p.store_shapes(trn))
+ return 1;
+ data+= p.get_data_size();
+ }
+ return 0;
+}
+
+
const Geometry::Class_info *Gis_multi_polygon::get_class_info() const
{
return &multipolygon_class;
@@ -1700,24 +2131,41 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb)
uint32 no_pos= wkb->length();
Geometry_buffer buffer;
Geometry *g;
+ char next_sym;
if (wkb->reserve(4, 512))
return 1;
wkb->length(wkb->length()+4); // Reserve space for points
- for (;;)
+ if (!(next_sym= trs->next_symbol()))
+ return 1;
+
+ if (next_sym != ')')
{
- if (!(g= create_from_wkt(&buffer, trs, wkb)))
+ LEX_STRING next_word;
+ if (trs->lookup_next_word(&next_word))
return 1;
- if (g->get_class_info()->m_type_id == wkb_geometrycollection)
+ if (next_word.length != 5 ||
+ (my_strnncoll(&my_charset_latin1,
+ (const uchar*) "empty", 5,
+ (const uchar*) next_word.str, 5) != 0))
{
- trs->set_error_msg("Unexpected GEOMETRYCOLLECTION");
- return 1;
+ for (;;)
+ {
+ if (!(g= create_from_wkt(&buffer, trs, wkb)))
+ return 1;
+
+ if (g->get_class_info()->m_type_id == wkb_geometrycollection)
+ {
+ trs->set_error_msg("Unexpected GEOMETRYCOLLECTION");
+ return 1;
+ }
+ n_objects++;
+ if (trs->skip_char(',')) // Didn't find ','
+ break;
+ }
}
- n_objects++;
- if (trs->skip_char(',')) // Didn't find ','
- break;
}
wkb->write_at_position(no_pos, n_objects);
@@ -1725,6 +2173,50 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb)
}
+uint Gis_geometry_collection::init_from_opresult(String *bin,
+ const char *opres,
+ uint res_len)
+{
+ const char *opres_orig= opres;
+ Geometry_buffer buffer;
+ Geometry *geom;
+ int g_len;
+ uint32 wkb_type;
+ int no_pos= bin->length();
+ uint32 n_objects= 0;
+
+ if (bin->reserve(4, 512))
+ return 0;
+ bin->q_append(n_objects);
+
+ while (res_len)
+ {
+ switch ((Gcalc_function::shape_type) uint4korr(opres))
+ {
+ case Gcalc_function::shape_point: wkb_type= wkb_point; break;
+ case Gcalc_function::shape_line: wkb_type= wkb_linestring; break;
+ case Gcalc_function::shape_polygon: wkb_type= wkb_polygon; break;
+ default: wkb_type= 0; DBUG_ASSERT(FALSE);
+ };
+
+ if (bin->reserve(WKB_HEADER_SIZE, 512))
+ return 0;
+
+ bin->q_append((char) wkb_ndr);
+ bin->q_append(wkb_type);
+
+ if (!(geom= create_by_typeid(&buffer, wkb_type)) ||
+ !(g_len= geom->init_from_opresult(bin, opres, res_len)))
+ return 0;
+ opres+= g_len;
+ res_len-= g_len;
+ n_objects++;
+ }
+ bin->write_at_position(no_pos, n_objects);
+ return (uint) (opres - opres_orig);
+}
+
+
uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len,
wkbByteOrder bo, String *res)
{
@@ -1780,6 +2272,13 @@ bool Gis_geometry_collection::get_data_as_wkt(String *txt,
n_objects= uint4korr(data);
data+= 4;
+ if (n_objects == 0)
+ {
+ txt->append(STRING_WITH_LEN(" EMPTY"), 512);
+ goto exit;
+ }
+
+ txt->qs_append('(');
while (n_objects--)
{
uint32 wkb_type;
@@ -1794,10 +2293,11 @@ bool Gis_geometry_collection::get_data_as_wkt(String *txt,
geom->set_data_ptr(data, (uint) (m_data_end - data));
if (geom->as_wkt(txt, &data))
return 1;
- if (txt->append(STRING_WITH_LEN(","), 512))
+ if (n_objects && txt->append(STRING_WITH_LEN(","), 512))
return 1;
}
- txt->length(txt->length() - 1);
+ txt->qs_append(')');
+exit:
*end= data;
return 0;
}
@@ -1814,6 +2314,8 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
return 1;
n_objects= uint4korr(data);
data+= 4;
+ if (n_objects == 0)
+ return 1;
while (n_objects--)
{
@@ -1835,6 +2337,82 @@ bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
}
+int Gis_geometry_collection::area(double *ar, const char **end) const
+{
+ uint32 n_objects;
+ const char *data= m_data;
+ Geometry_buffer buffer;
+ Geometry *geom;
+ double result;
+
+ if (no_data(data, 4))
+ return 1;
+ n_objects= uint4korr(data);
+ data+= 4;
+ if (n_objects == 0)
+ return 1;
+
+ result= 0.0;
+ while (n_objects--)
+ {
+ uint32 wkb_type;
+
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
+
+ if (!(geom= create_by_typeid(&buffer, wkb_type)))
+ return 1;
+ geom->set_data_ptr(data, (uint32) (m_data_end - data));
+ if (geom->area(ar, &data))
+ return 1;
+ result+= *ar;
+ }
+ *end= data;
+ *ar= result;
+ return 0;
+}
+
+
+int Gis_geometry_collection::geom_length(double *len, const char **end) const
+{
+ uint32 n_objects;
+ const char *data= m_data;
+ Geometry_buffer buffer;
+ Geometry *geom;
+ double result;
+
+ if (no_data(data, 4))
+ return 1;
+ n_objects= uint4korr(data);
+ data+= 4;
+ if (n_objects == 0)
+ return 1;
+
+ result= 0.0;
+ while (n_objects--)
+ {
+ uint32 wkb_type;
+
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
+
+ if (!(geom= create_by_typeid(&buffer, wkb_type)))
+ return 1;
+ geom->set_data_ptr(data, (uint32) (m_data_end - data));
+ if (geom->geom_length(len, &data))
+ return 1;
+ result+= *len;
+ }
+ *end= data;
+ *len= result;
+ return 0;
+}
+
+
int Gis_geometry_collection::num_geometries(uint32 *num) const
{
if (no_data(m_data, 4))
@@ -1874,7 +2452,7 @@ int Gis_geometry_collection::geometry_n(uint32 num, String *result) const
} while (--num);
/* Copy found object to result */
- if (result->reserve(1+4+length))
+ if (result->reserve(1 + 4 + length))
return 1;
result->q_append((char) wkb_ndr);
result->q_append((uint32) wkb_type);
@@ -1935,6 +2513,48 @@ bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const
return 0;
}
+
+int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn) const
+{
+ uint32 n_objects;
+ const char *data= m_data;
+ Geometry_buffer buffer;
+ Geometry *geom;
+
+ if (no_data(data, 4))
+ return 1;
+ n_objects= uint4korr(data);
+ data+= 4;
+
+ if (!n_objects)
+ {
+ trn->empty_shape();
+ return 0;
+ }
+
+ if (trn->start_collection(n_objects))
+ return 1;
+
+ while (n_objects--)
+ {
+ uint32 wkb_type;
+
+ if (no_data(data, WKB_HEADER_SIZE))
+ return 1;
+ wkb_type= uint4korr(data + 1);
+ data+= WKB_HEADER_SIZE;
+ if (!(geom= create_by_typeid(&buffer, wkb_type)))
+ return 1;
+ geom->set_data_ptr(data, (uint32) (m_data_end - data));
+ if (geom->store_shapes(trn))
+ return 1;
+
+ data+= geom->get_data_size();
+ }
+ return 0;
+}
+
+
const Geometry::Class_info *Gis_geometry_collection::get_class_info() const
{
return &geometrycollection_class;
diff --git a/sql/spatial.h b/sql/spatial.h
index e93540db862..bea9ade9598 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -23,6 +23,8 @@
class Gis_read_stream;
+#include "gcalc_tools.h"
+
const uint SRID_SIZE= 4;
const uint SIZEOF_STORED_DOUBLE= 8;
const uint POINT_DATA_SIZE= SIZEOF_STORED_DOUBLE*2;
@@ -247,16 +249,19 @@ public:
virtual const Class_info *get_class_info() const=0;
virtual uint32 get_data_size() const=0;
virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0;
-
/* returns the length of the wkb that was read */
virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
String *res)=0;
+ virtual uint init_from_opresult(String *bin,
+ const char *opres, uint res_len)
+ { return init_from_wkb(opres + 4, UINT_MAX32, wkb_ndr, bin) + 4; }
+
virtual bool get_data_as_wkt(String *txt, const char **end) const=0;
virtual bool get_mbr(MBR *mbr, const char **end) const=0;
virtual bool dimension(uint32 *dim, const char **end) const=0;
virtual int get_x(double *x) const { return -1; }
virtual int get_y(double *y) const { return -1; }
- virtual int geom_length(double *len) const { return -1; }
+ virtual int geom_length(double *len, const char **end) const { return -1; }
virtual int area(double *ar, const char **end) const { return -1;}
virtual int is_closed(int *closed) const { return -1; }
virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; }
@@ -269,6 +274,7 @@ public:
virtual int point_n(uint32 num, String *result) const { return -1; }
virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
virtual int geometry_n(uint32 num, String *result) const { return -1; }
+ virtual int store_shapes(Gcalc_shape_transporter *trn) const=0;
public:
static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
@@ -278,20 +284,11 @@ public:
static Geometry *create_from_wkt(Geometry_buffer *buffer,
Gis_read_stream *trs, String *wkt,
bool init_stream=1);
- static Geometry *create_from_wkb(Geometry_buffer *buffer, const char *wkb,
- uint32 len, String *res);
- int as_wkt(String *wkt, const char **end)
- {
- uint32 len= (uint) get_class_info()->m_name.length;
- if (wkt->reserve(len + 2, 512))
- return 1;
- wkt->qs_append(get_class_info()->m_name.str, len);
- wkt->qs_append('(');
- if (get_data_as_wkt(wkt, end))
- return 1;
- wkt->qs_append(')');
- return 0;
- }
+ static Geometry *create_from_wkb(Geometry_buffer *buffer,
+ const char *wkb, uint32 len, String *res);
+ static int create_from_opresult(Geometry_buffer *g_buf,
+ String *res, Gcalc_result_receiver &rr);
+ int as_wkt(String *wkt, const char **end);
inline void set_data_ptr(const char *data, uint32 data_len)
{
@@ -369,12 +366,15 @@ public:
return 0;
}
+ int geom_length(double *len, const char **end) const;
+ int area(double *ar, const char **end) const;
bool dimension(uint32 *dim, const char **end) const
{
*dim= 0;
*end= 0; /* No default end */
return 0;
}
+ int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -391,7 +391,8 @@ public:
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
bool get_data_as_wkt(String *txt, const char **end) const;
bool get_mbr(MBR *mbr, const char **end) const;
- int geom_length(double *len) const;
+ int geom_length(double *len, const char **end) const;
+ int area(double *ar, const char **end) const;
int is_closed(int *closed) const;
int num_points(uint32 *n_points) const;
int start_point(String *point) const;
@@ -403,6 +404,7 @@ public:
*end= 0; /* No default end */
return 0;
}
+ int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -417,6 +419,7 @@ public:
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
+ uint init_from_opresult(String *bin, const char *opres, uint res_len);
bool get_data_as_wkt(String *txt, const char **end) const;
bool get_mbr(MBR *mbr, const char **end) const;
int area(double *ar, const char **end) const;
@@ -431,6 +434,7 @@ public:
*end= 0; /* No default end */
return 0;
}
+ int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -445,6 +449,7 @@ public:
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
+ uint init_from_opresult(String *bin, const char *opres, uint res_len);
bool get_data_as_wkt(String *txt, const char **end) const;
bool get_mbr(MBR *mbr, const char **end) const;
int num_geometries(uint32 *num) const;
@@ -455,6 +460,7 @@ public:
*end= 0; /* No default end */
return 0;
}
+ int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -469,11 +475,12 @@ public:
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
+ uint init_from_opresult(String *bin, const char *opres, uint res_len);
bool get_data_as_wkt(String *txt, const char **end) const;
bool get_mbr(MBR *mbr, const char **end) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
- int geom_length(double *len) const;
+ int geom_length(double *len, const char **end) const;
int is_closed(int *closed) const;
bool dimension(uint32 *dim, const char **end) const
{
@@ -481,6 +488,7 @@ public:
*end= 0; /* No default end */
return 0;
}
+ int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
@@ -507,7 +515,9 @@ public:
*end= 0; /* No default end */
return 0;
}
+ int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
+ uint init_from_opresult(String *bin, const char *opres, uint res_len);
};
@@ -521,11 +531,15 @@ public:
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
+ uint init_from_opresult(String *bin, const char *opres, uint res_len);
bool get_data_as_wkt(String *txt, const char **end) const;
bool get_mbr(MBR *mbr, const char **end) const;
+ int area(double *ar, const char **end) const;
+ int geom_length(double *len, const char **end) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
bool dimension(uint32 *dim, const char **end) const;
+ int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
};
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 2411c9c33ea..22c32085785 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8133,6 +8133,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
table_list->table->map= table_list->map_exec;
table_list->table->maybe_null= table_list->maybe_null_exec;
table_list->table->pos_in_table_list= table_list;
+ if (table_list->process_index_hints(table_list->table))
+ DBUG_RETURN(1);
}
select_lex->leaf_tables.push_back(table_list);
}
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 30c72d603f4..412686a49c9 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -192,17 +192,14 @@
#define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1ULL << 26)
#define OPTIMIZER_SWITCH_LAST (1ULL << 26)
-/*
-TODO: Materialization is off by default to mimic 5.1/5.2 behavior.
-Once cost based choice between materialization and in-to-exists should be
-enabled by default, add OPTIMIZER_SWITCH_MATERIALIZATION
-*/
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION | \
OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT | \
+ OPTIMIZER_SWITCH_INDEX_COND_PUSHDOWN | \
OPTIMIZER_SWITCH_TABLE_ELIMINATION | \
OPTIMIZER_SWITCH_IN_TO_EXISTS | \
+ OPTIMIZER_SWITCH_MATERIALIZATION | \
OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE|\
OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN|\
OPTIMIZER_SWITCH_JOIN_CACHE_INCREMENTAL | \
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4ce278c98ef..07daaa2bd5c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -843,7 +843,7 @@ inject_jtbm_conds(JOIN *join, List<TABLE_LIST> *join_list, Item **join_where)
double rows;
double read_time;
- DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
+ //DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
subq_pred->optimize(&rows, &read_time);
subq_pred->jtbm_read_time= read_time;
@@ -15041,9 +15041,15 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
{
/*
HAVING will be checked after processing aggregate functions,
- But WHERE should checkd here (we alredy have read tables)
+ But WHERE should checkd here (we alredy have read tables).
+ If there is join->exec_const_cond, and all tables are constant, then it
+ is equivalent to join->conds. exec_const_cond is already checked in the
+ beginning of JOIN::exec. If it is false, JOIN::exec returns zero
+ result already there, therefore execution reaches this point only if
+ exec_const_cond is TRUE. Since it is equvalent to join->conds, then
+ join->conds is also TRUE.
*/
- if (!join->conds || join->conds->val_int())
+ if (!join->conds || join->exec_const_cond || join->conds->val_int())
{
error= (*end_select)(join, 0, 0);
if (error == NESTED_LOOP_OK || error == NESTED_LOOP_QUERY_LIMIT)
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index e0a4f77ddd6..f70dc7a0f8a 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -12095,7 +12095,7 @@ static MYSQL_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_sample_pages,
"The number of index pages to sample when calculating statistics (default 8)",
NULL, NULL, 8, 1, ~0ULL, 0);
-static MYSQL_SYSVAR_ULONG(stats_auto_update, srv_stats_auto_update,
+static MYSQL_SYSVAR_ULINT(stats_auto_update, srv_stats_auto_update,
PLUGIN_VAR_RQCMDARG,
"Enable/Disable InnoDB's auto update statistics of indexes. "
"(except for ANALYZE TABLE command) 0:disable 1:enable",
@@ -12121,7 +12121,7 @@ static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
"Disable with --skip-innodb-adaptive-hash-index.",
NULL, innodb_adaptive_hash_index_update, TRUE);
-static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
+static MYSQL_SYSVAR_ULINT(adaptive_hash_index_partitions, btr_search_index_num,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
NULL, NULL, 1, 1, sizeof(ulint) * 8, 0);
@@ -12338,7 +12338,7 @@ static MYSQL_SYSVAR_ULINT(checkpoint_age_target, srv_checkpoint_age_target,
"Control soft limit of checkpoint age. (0 : not control)",
NULL, NULL, 0, 0, ~0UL, 0);
-static MYSQL_SYSVAR_ULONG(flush_neighbor_pages, srv_flush_neighbor_pages,
+static MYSQL_SYSVAR_ULINT(flush_neighbor_pages, srv_flush_neighbor_pages,
PLUGIN_VAR_RQCMDARG,
"Enable/Disable flushing also neighbor pages. 0:disable 1:enable",
NULL, NULL, 1, 0, 1, 0);
@@ -12412,7 +12412,7 @@ static MYSQL_SYSVAR_ULONG(import_table_from_xtrabackup, srv_expand_import,
"Enable/Disable converting automatically *.ibd files when import tablespace.",
NULL, NULL, 0, 0, 1, 0);
-static MYSQL_SYSVAR_ULONG(dict_size_limit, srv_dict_size_limit,
+static MYSQL_SYSVAR_ULINT(dict_size_limit, srv_dict_size_limit,
PLUGIN_VAR_RQCMDARG,
"Limit the allocated memory for dictionary cache. (0: unlimited)",
NULL, NULL, 0, 0, LONG_MAX, 0);
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index 1c00e219cd3..2de0ed190ab 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -240,11 +240,11 @@ extern ulong srv_ibuf_accel_rate;
extern ulint srv_checkpoint_age_target;
extern ulint srv_flush_neighbor_pages;
extern ulint srv_deprecated_enable_unsafe_group_commit;
-extern ulint srv_read_ahead;
-extern ulint srv_adaptive_flushing_method;
+extern ulong srv_read_ahead;
+extern ulong srv_adaptive_flushing_method;
extern ulong srv_expand_import;
-extern ulint srv_pass_corrupt_table;
+extern ulong srv_pass_corrupt_table;
extern ulint srv_dict_size_limit;
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
index 1b38c9cef7e..0606de2e89a 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -434,10 +434,10 @@ UNIV_INTERN ulint srv_checkpoint_age_target = 0;
UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */
UNIV_INTERN ulint srv_deprecated_enable_unsafe_group_commit = 0;
-UNIV_INTERN ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
-UNIV_INTERN ulint srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
+UNIV_INTERN ulong srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
+UNIV_INTERN ulong srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
-UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
+UNIV_INTERN ulong srv_expand_import = 0; /* 0:disable 1:enable */
UNIV_INTERN ulong srv_pass_corrupt_table = 0; /* 0:disable 1:enable */
UNIV_INTERN ulint srv_dict_size_limit = 0;