summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-03-31 08:01:03 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-03-31 08:01:03 +0300
commitd6d3d9ae2ffb1df8eebfe0c922394bbc7b12e4ed (patch)
tree341f053652cf1e93acf89180a0b072f7d43ef1e1
parent96475b78c55141164ecf2719e000d189e4bcbc3d (diff)
parent99945d77d748470fbb3939be5f7d0e36d24d8097 (diff)
downloadmariadb-git-d6d3d9ae2ffb1df8eebfe0c922394bbc7b12e4ed.tar.gz
Merge 10.2 into 10.3
-rw-r--r--cmake/os/WindowsCache.cmake1
-rw-r--r--mysql-test/main/gis-json.result4
-rw-r--r--mysql-test/main/gis-precise.result111
-rw-r--r--mysql-test/main/gis-precise.test78
-rw-r--r--mysql-test/main/userstat.test1
-rw-r--r--mysql-test/suite/binlog/t/binlog_xa_recover.test1
-rw-r--r--mysql-test/suite/galera/r/galera_ssl_upgrade.result1
-rw-r--r--mysql-test/suite/galera/t/galera_ssl_upgrade.test2
-rw-r--r--mysql-test/suite/innodb_fts/r/misc_debug.result26
-rw-r--r--mysql-test/suite/innodb_fts/t/misc_debug.test31
-rw-r--r--mysql-test/suite/innodb_gis/t/1.test12
-rw-r--r--mysql-test/suite/innodb_gis/t/bug16236208.test1
-rw-r--r--mysql-test/suite/innodb_gis/t/create_spatial_index.test1
-rw-r--r--mysql-test/suite/innodb_gis/t/gis.test15
-rw-r--r--mysql-test/suite/innodb_gis/t/precise.test1
-rw-r--r--mysql-test/suite/innodb_gis/t/rtree.test6
-rw-r--r--mysql-test/suite/plugins/r/server_audit.result4
-rw-r--r--mysql-test/suite/plugins/t/server_audit.test4
-rw-r--r--scripts/CMakeLists.txt1
-rw-r--r--scripts/mysql_to_mariadb.sql22
-rw-r--r--scripts/wsrep_sst_mariabackup.sh6
-rw-r--r--sql/item_create.cc38
-rw-r--r--sql/item_geofunc.cc146
-rw-r--r--sql/item_geofunc.h16
-rw-r--r--sql/signal_handler.cc14
-rw-r--r--sql/spatial.cc188
-rw-r--r--sql/spatial.h22
-rw-r--r--sql/sql_test.cc2
-rw-r--r--sql/wsrep_mysqld.cc22
-rw-r--r--storage/innobase/handler/ha_innodb.cc37
-rw-r--r--storage/innobase/lock/lock0lock.cc173
-rw-r--r--storage/innobase/row/row0import.cc85
-rw-r--r--storage/innobase/row/row0merge.cc2
-rw-r--r--support-files/rpm/server-posttrans.sh11
-rwxr-xr-xtests/grant.pl750
35 files changed, 873 insertions, 962 deletions
diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake
index b7adeb4c8cc..7202740e51f 100644
--- a/cmake/os/WindowsCache.cmake
+++ b/cmake/os/WindowsCache.cmake
@@ -90,6 +90,7 @@ SET(HAVE_LRAND48 CACHE INTERNAL "")
SET(HAVE_LSTAT CACHE INTERNAL "")
SET(HAVE_MADVISE CACHE INTERNAL "")
SET(HAVE_MALLINFO CACHE INTERNAL "")
+SET(HAVE_MALLINFO2 CACHE INTERNAL "")
SET(HAVE_MALLOC_H 1 CACHE INTERNAL "")
SET(HAVE_MEMALIGN CACHE INTERNAL "")
SET(HAVE_MEMCPY 1 CACHE INTERNAL "")
diff --git a/mysql-test/main/gis-json.result b/mysql-test/main/gis-json.result
index d507a9994ff..e52a7c809c6 100644
--- a/mysql-test/main/gis-json.result
+++ b/mysql-test/main/gis-json.result
@@ -62,9 +62,9 @@ SELECT st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features":
st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}'))
GEOMETRYCOLLECTION(POINT(102 0.5))
SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',5));
-ERROR HY000: Incorrect option value: '5' for function ST_GeometryFromJSON
+ERROR HY000: Incorrect option value: '5' for function ST_GeomFromGeoJSON
SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',1));
-ERROR 22023: Invalid GIS data provided to function ST_GeometryFromJSON.
+ERROR 22023: Invalid GIS data provided to function ST_GeomFromGeoJSON.
SELECT ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2));
ST_AsText(ST_GeomFromGeoJSON('{ "type": "Point", "coordinates": [5.3, 15.0, 4.3]}',2))
POINT(5.3 15)
diff --git a/mysql-test/main/gis-precise.result b/mysql-test/main/gis-precise.result
index 32b536b6e7f..c72debb6f73 100644
--- a/mysql-test/main/gis-precise.result
+++ b/mysql-test/main/gis-precise.result
@@ -806,3 +806,114 @@ SRID(GEOMETRYFROMTEXT(' MULTIPOINT(8 4,5 0,7 8,6 9,3 4,7 3,5 5) '))));
ASTEXT(ST_BUFFER(POLYGONFROMTEXT(' POLYGON((9 9,5 2,4 5,9 9))'),
SRID(GEOMETRYFROMTEXT(' MULTIPOINT(8 4,5 0,7 8,6 9,3 4,7 3,5 5) '))))
POLYGON((9 9,5 2,4 5,9 9))
+#
+# MDEV-13467 Feature request: Support for ST_Distance_Sphere()
+#
+SELECT ST_DISTANCE_SPHERE();
+ERROR 42000: Incorrect parameter count in the call to native function 'ST_DISTANCE_SPHERE'
+SELECT ST_DISTANCE_SPHERE(NULL);
+ERROR 42000: Incorrect parameter count in the call to native function 'ST_DISTANCE_SPHERE'
+SELECT ST_DISTANCE_SPHERE(NULL, NULL);
+ST_DISTANCE_SPHERE(NULL, NULL)
+NULL
+SELECT ST_DISTANCE_SPHERE(NULL, NULL, 3);
+ST_DISTANCE_SPHERE(NULL, NULL, 3)
+NULL
+SELECT ST_DISTANCE_SPHERE(NULL, 1, 3);
+ST_DISTANCE_SPHERE(NULL, 1, 3)
+NULL
+SELECT ST_DISTANCE_SPHERE(1, NULL, 3);
+ST_DISTANCE_SPHERE(1, NULL, 3)
+NULL
+SELECT ST_DISTANCE_SPHERE(1, 1);
+ERROR 22023: Invalid GIS data provided to function ST_Distance_Sphere.
+SELECT ST_DISTANCE_SPHERE(1, 1, 3);
+ERROR 22023: Invalid GIS data provided to function ST_Distance_Sphere.
+SELECT ST_DISTANCE_SPHERE(1, 1, NULL);
+ST_DISTANCE_SPHERE(1, 1, NULL)
+NULL
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('LINESTRING(0 0, 1 1)'));
+ERROR HY000: Internal error: st_distance_sphere
+# Test Points and radius
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'));
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'))
+157249.0357231545
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(-1 -1)'), ST_GEOMFROMTEXT('POINT(-2 -2)')), 10);
+TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(-1 -1)'), ST_GEOMFROMTEXT('POINT(-2 -2)')), 10)
+157225.0865419108
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 1);
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 1)
+0.024682056391766436
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 0);
+ERROR HY000: Internal error: Radius must be greater than zero.
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), -1);
+ERROR HY000: Internal error: Radius must be greater than zero.
+# Test longitude/lattitude
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10);
+TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10)
+157225.0865419108
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(2 1)')), 10);
+TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(2 1)')), 10)
+222355.4901806686
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10);
+TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10)
+222389.3645969269
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(2 1)'));
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(2 1)'))
+157249.0357231545
+# Test Points - Multipoints
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1)'));
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1)'))
+157249.0357231545
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 1)'), ST_GEOMFROMTEXT('POINT(0 0)'));
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 1)'), ST_GEOMFROMTEXT('POINT(0 0)'))
+157249.0357231545
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'));
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'))
+157249.0357231545
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'));
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'))
+157249.0357231545
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'), 1);
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'), 1)
+0.024682056391766436
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'), 1);
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'), 1)
+0.024682056391766436
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1, 3 4)'), 1);
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1, 3 4)'), 1)
+0.024682056391766436
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1,5 6)'), 1);
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1,5 6)'), 1)
+0.024682056391766436
+# Test Multipoints - Multipoints
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'));
+ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'))
+0
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )')), 10);
+TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )')), 10)
+314282.5644496733
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )')), 10);
+TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )')), 10)
+314282.5644496733
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),1), 17);
+TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),1), 17)
+0.04933028646581131
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),0);
+ERROR HY000: Internal error: Radius must be greater than zero.
+set @pt1 = ST_GeomFromText('POINT(190 -30)');
+set @pt2 = ST_GeomFromText('POINT(-30 50)');
+SELECT ST_Distance_Sphere(@pt1, @pt2);
+ERROR HY000: Out of range error: Longitude should be [-180,180] in function ST_Distance_Sphere.
+set @pt1 = ST_GeomFromText('POINT(135 -30)');
+set @pt2 = ST_GeomFromText('POINT(-30 91)');
+SELECT ST_Distance_Sphere(@pt1, @pt2);
+ERROR HY000: Out of range error: Latitude should be [-90,90] in function ST_Distance_Sphere.
+set @zenica = ST_GeomFromText('POINT(17.907743 44.203438)');
+set @sarajevo = ST_GeomFromText('POINT(18.413076 43.856258)');
+SELECT TRUNCATE(ST_Distance_Sphere(@zenica, @sarajevo), 10);
+TRUNCATE(ST_Distance_Sphere(@zenica, @sarajevo), 10)
+55878.5933759170
+SELECT TRUNCATE(ST_Distance_Sphere(@sarajevo, @zenica), 10);
+TRUNCATE(ST_Distance_Sphere(@sarajevo, @zenica), 10)
+55878.5933759170
diff --git a/mysql-test/main/gis-precise.test b/mysql-test/main/gis-precise.test
index 24f4ac9113e..da72a0c4d8a 100644
--- a/mysql-test/main/gis-precise.test
+++ b/mysql-test/main/gis-precise.test
@@ -394,3 +394,81 @@ with cte1 as( select (st_symdifference(point(1,1),point(1,1))) as a1 ), cte2 a
--source include/gis_debug.inc
+
+--echo #
+--echo # MDEV-13467 Feature request: Support for ST_Distance_Sphere()
+--echo #
+
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+SELECT ST_DISTANCE_SPHERE();
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+SELECT ST_DISTANCE_SPHERE(NULL);
+SELECT ST_DISTANCE_SPHERE(NULL, NULL);
+# NULL args and optional radius will return NULL
+SELECT ST_DISTANCE_SPHERE(NULL, NULL, 3);
+# At least 1 NULL arg and optional radius will return NULL
+SELECT ST_DISTANCE_SPHERE(NULL, 1, 3);
+# At least 1 NULL arg and optional radius will return NULL
+SELECT ST_DISTANCE_SPHERE(1, NULL, 3);
+# Return ER_GIS_INVALID_DATA for invalid geometry
+--error ER_GIS_INVALID_DATA
+SELECT ST_DISTANCE_SPHERE(1, 1);
+--error ER_GIS_INVALID_DATA
+SELECT ST_DISTANCE_SPHERE(1, 1, 3);
+# Return NULL if radius is NULL
+SELECT ST_DISTANCE_SPHERE(1, 1, NULL);
+# Wrong geometry
+--error ER_INTERNAL_ERROR
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('LINESTRING(0 0, 1 1)'));
+
+--echo # Test Points and radius
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'));
+# make bb x86 happy
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(-1 -1)'), ST_GEOMFROMTEXT('POINT(-2 -2)')), 10);
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 1);
+--error ER_INTERNAL_ERROR
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), 0);
+--error ER_INTERNAL_ERROR
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('POINT(1 1)'), -1);
+--echo # Test longitude/lattitude
+# make bb x86 happy
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10);
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 1)'), ST_GEOMFROMTEXT('POINT(2 1)')), 10);
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(1 2)')), 10);
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(1 0)'), ST_GEOMFROMTEXT('POINT(2 1)'));
+--echo # Test Points - Multipoints
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1)'));
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 1)'), ST_GEOMFROMTEXT('POINT(0 0)'));
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'));
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'));
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(1 1,2 2)'), 1);
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2,1 1)'), 1);
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1, 3 4)'), 1);
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('POINT(0 0)'), ST_GEOMFROMTEXT('MULTIPOINT(2 2, 1 1,5 6)'), 1);
+--echo # Test Multipoints - Multipoints
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )'));
+# make bb x86 happy
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(3 4,8 9 )')), 10);
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )')), 10);
+# make bb x86 happy
+SELECT TRUNCATE(ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),1), 17);
+--error ER_INTERNAL_ERROR
+SELECT ST_DISTANCE_SPHERE(ST_GEOMFROMTEXT('MULTIPOINT(1 2,1 1 )'), ST_GEOMFROMTEXT('MULTIPOINT(8 9,3 4 )'),0);
+
+# Longitude out of range [-180,180]
+set @pt1 = ST_GeomFromText('POINT(190 -30)');
+set @pt2 = ST_GeomFromText('POINT(-30 50)');
+--error ER_STD_OUT_OF_RANGE_ERROR
+SELECT ST_Distance_Sphere(@pt1, @pt2);
+
+# Latitude out of range [-90, 90]
+set @pt1 = ST_GeomFromText('POINT(135 -30)');
+set @pt2 = ST_GeomFromText('POINT(-30 91)');
+--error ER_STD_OUT_OF_RANGE_ERROR
+SELECT ST_Distance_Sphere(@pt1, @pt2);
+
+# POINT in form (longitude[-180, 180] latitude[-90, 90])
+set @zenica = ST_GeomFromText('POINT(17.907743 44.203438)');
+set @sarajevo = ST_GeomFromText('POINT(18.413076 43.856258)');
+SELECT TRUNCATE(ST_Distance_Sphere(@zenica, @sarajevo), 10);
+SELECT TRUNCATE(ST_Distance_Sphere(@sarajevo, @zenica), 10);
diff --git a/mysql-test/main/userstat.test b/mysql-test/main/userstat.test
index 42fe1c2ad17..cc7ddd58e11 100644
--- a/mysql-test/main/userstat.test
+++ b/mysql-test/main/userstat.test
@@ -5,6 +5,7 @@
-- source include/have_innodb.inc
-- source include/have_log_bin.inc
+-- source include/have_perfschema.inc
select variable_value from information_schema.global_status where variable_name="handler_read_key" into @global_read_key;
show columns from information_schema.client_statistics;
diff --git a/mysql-test/suite/binlog/t/binlog_xa_recover.test b/mysql-test/suite/binlog/t/binlog_xa_recover.test
index 51c30ee705d..3b2a7e45392 100644
--- a/mysql-test/suite/binlog/t/binlog_xa_recover.test
+++ b/mysql-test/suite/binlog/t/binlog_xa_recover.test
@@ -8,6 +8,7 @@
--source include/have_debug.inc
--source include/have_debug_sync.inc
--source include/have_binlog_format_row.inc
+--source include/have_perfschema.inc
# Valgrind does not work well with test that crashes the server
--source include/not_valgrind.inc
diff --git a/mysql-test/suite/galera/r/galera_ssl_upgrade.result b/mysql-test/suite/galera/r/galera_ssl_upgrade.result
index 818469bf6ad..8aab135c6a2 100644
--- a/mysql-test/suite/galera/r/galera_ssl_upgrade.result
+++ b/mysql-test/suite/galera/r/galera_ssl_upgrade.result
@@ -1,3 +1,4 @@
+call mtr.add_suppression("WSREP: write_handler(): protocol is shutdown");
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
VARIABLE_VALUE = 'Synced'
1
diff --git a/mysql-test/suite/galera/t/galera_ssl_upgrade.test b/mysql-test/suite/galera/t/galera_ssl_upgrade.test
index b69e390533f..33c5a43df9d 100644
--- a/mysql-test/suite/galera/t/galera_ssl_upgrade.test
+++ b/mysql-test/suite/galera/t/galera_ssl_upgrade.test
@@ -8,6 +8,8 @@
--source include/have_innodb.inc
--source include/have_ssl_communication.inc
+call mtr.add_suppression("WSREP: write_handler(): protocol is shutdown");
+
SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment';
SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
diff --git a/mysql-test/suite/innodb_fts/r/misc_debug.result b/mysql-test/suite/innodb_fts/r/misc_debug.result
index f1110797f33..10e3cf8874d 100644
--- a/mysql-test/suite/innodb_fts/r/misc_debug.result
+++ b/mysql-test/suite/innodb_fts/r/misc_debug.result
@@ -26,3 +26,29 @@ SET DEBUG_DBUG="+d,fts_instrument_sync";
INSERT INTO t1 VALUES(1, "mariadb");
ALTER TABLE t1 FORCE;
DROP TABLE t2, t1;
+#
+# MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
+#
+CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
+connect con1,localhost,root,,test;
+SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL s1 WAIT_FOR g1';
+SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
+ALTER TABLE t1 ADD FULLTEXT(c);
+connection default;
+SET DEBUG_SYNC='now WAIT_FOR s1';
+KILL QUERY @id;
+SET DEBUG_SYNC='now SIGNAL g1 WAIT_FOR s2';
+START TRANSACTION;
+SELECT * FROM t1;
+a b c
+SET DEBUG_SYNC='now SIGNAL s2';
+connection con1;
+ERROR 70100: Query execution was interrupted
+disconnect con1;
+connection default;
+SET DEBUG_SYNC=RESET;
+ALTER TABLE t1 ADD bl INT AS (LENGTH(b)) VIRTUAL;
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb_fts/t/misc_debug.test b/mysql-test/suite/innodb_fts/t/misc_debug.test
index aaf628abe6d..461e3f1d9d4 100644
--- a/mysql-test/suite/innodb_fts/t/misc_debug.test
+++ b/mysql-test/suite/innodb_fts/t/misc_debug.test
@@ -5,6 +5,8 @@
--source include/have_innodb.inc
--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/count_sessions.inc
# Following test is for Bug 14668777 - ASSERT ON IB_VECTOR_SIZE(
# TABLE->FTS->INDEXES, ALTER TABLE
@@ -52,3 +54,32 @@ INSERT INTO t1 VALUES(1, "mariadb");
ALTER TABLE t1 FORCE;
# Cleanup
DROP TABLE t2, t1;
+
+--echo #
+--echo # MDEV-25200 Index count mismatch due to aborted FULLTEXT INDEX
+--echo #
+CREATE TABLE t1(a INT, b TEXT, c TEXT, FULLTEXT INDEX(b)) ENGINE=InnoDB;
+connect(con1,localhost,root,,test);
+let $ID= `SELECT @id := CONNECTION_ID()`;
+SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL s1 WAIT_FOR g1';
+SET DEBUG_SYNC='innodb_commit_inplace_alter_table_enter SIGNAL s2 WAIT_FOR g2';
+send ALTER TABLE t1 ADD FULLTEXT(c);
+connection default;
+SET DEBUG_SYNC='now WAIT_FOR s1';
+let $ignore= `SELECT @id := $ID`;
+KILL QUERY @id;
+SET DEBUG_SYNC='now SIGNAL g1 WAIT_FOR s2';
+START TRANSACTION;
+SELECT * FROM t1;
+SET DEBUG_SYNC='now SIGNAL s2';
+connection con1;
+--error ER_QUERY_INTERRUPTED
+reap;
+disconnect con1;
+connection default;
+SET DEBUG_SYNC=RESET;
+# Exploit MDEV-17468 to force the table definition to be reloaded
+ALTER TABLE t1 ADD bl INT AS (LENGTH(b)) VIRTUAL;
+CHECK TABLE t1;
+DROP TABLE t1;
+--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/suite/innodb_gis/t/1.test b/mysql-test/suite/innodb_gis/t/1.test
index 7c9199c59ae..f08fdaddbda 100644
--- a/mysql-test/suite/innodb_gis/t/1.test
+++ b/mysql-test/suite/innodb_gis/t/1.test
@@ -393,7 +393,6 @@ insert into t1 values (1);
insert into t1 values (1.11);
--error 1416
insert into t1 values ("qwerty");
-# --error ER_GIS_INVALID_DATA
--error ER_BAD_NULL_ERROR
insert into t1 values (ST_pointfromtext('point(1,1)'));
@@ -437,7 +436,6 @@ select
ST_y(b) IS NULL
from t1;
-# --error ER_GIS_INVALID_DATA
select
MBRwithin(b, b) IS NULL, MBRcontains(b, b) IS NULL, MBRoverlaps(b, b) IS NULL,
MBRequals(b, b) IS NULL, MBRdisjoint(b, b) IS NULL, ST_touches(b, b) IS NULL,
@@ -466,7 +464,6 @@ DROP TABLE t1;
#
CREATE TABLE `t1` ( `col9` set('a'), `col89` date);
INSERT IGNORE INTO `t1` VALUES ('','0000-00-00');
-# --error ER_GIS_INVALID_DATA
select ST_geomfromtext(col9,col89) as a from t1;
DROP TABLE t1;
@@ -623,17 +620,11 @@ SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRwithin FROM t1 a1 JOIN
# MBROverlaps needs a few more tests, with point and line dimensions
-# --error ER_GIS_INVALID_DATA
SET @vert1 = ST_GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
-# --error ER_GIS_INVALID_DATA
SET @horiz1 = ST_GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
-# --error ER_GIS_INVALID_DATA
SET @horiz2 = ST_GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
-# --error ER_GIS_INVALID_DATA
SET @horiz3 = ST_GeomFromText('POLYGON ((2 0, 3 0, 2 0))');
-# --error ER_GIS_INVALID_DATA
SET @point1 = ST_GeomFromText('POLYGON ((0 0))');
-# --error ER_GIS_INVALID_DATA
SET @point2 = ST_GeomFromText('POLYGON ((-2 0))');
SELECT GROUP_CONCAT(a1.name ORDER BY a1.name) AS MBRoverlaps FROM t1 a1 WHERE MBROverlaps(a1.square, @vert1) GROUP BY a1.name;
@@ -773,10 +764,8 @@ SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUA
--echo # BUG#51875: crash when loading data into geometry function ST_polyfromwkb
--echo #
SET @a=0x00000000030000000100000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440;
-# --error ER_GIS_INVALID_DATA
SET @a=ST_POLYFROMWKB(@a);
SET @a=0x00000000030000000000000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440;
-# --error ER_GIS_INVALID_DATA
SET @a=ST_POLYFROMWKB(@a);
@@ -901,7 +890,6 @@ DROP TABLE g1;
CREATE TABLE g1(a TEXT NOT NULL, KEY(a(255)));
INSERT INTO g1 VALUES ('a'),('a');
-# --error ER_GIS_INVALID_DATA
SELECT 1 FROM g1 WHERE a >= ANY
(SELECT 1 FROM g1 WHERE a = ST_geomfromtext('') OR a) ;
diff --git a/mysql-test/suite/innodb_gis/t/bug16236208.test b/mysql-test/suite/innodb_gis/t/bug16236208.test
index b55ab1d0fd3..3a1fbefc52c 100644
--- a/mysql-test/suite/innodb_gis/t/bug16236208.test
+++ b/mysql-test/suite/innodb_gis/t/bug16236208.test
@@ -47,7 +47,6 @@ ST_GeomFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))'));
CREATE INDEX linestring_index ON linestring(linestring_nokey(5));
ALTER TABLE linestring ADD KEY (linestring_key(5));
-# --error ER_GIS_INVALID_DATA
SELECT ST_AsText(linestring_nokey) FROM linestring FORCE KEY (
linestring_key ) WHERE ST_CONTAINS( ST_GeomFromText('POLYGON( ( 3923 2815 , 4246
2122 , 4028 2971 , 4017 3019 , 3923 2815 ) )') , linestring_key ) AND
diff --git a/mysql-test/suite/innodb_gis/t/create_spatial_index.test b/mysql-test/suite/innodb_gis/t/create_spatial_index.test
index 7ddece9ad86..ef87a51d372 100644
--- a/mysql-test/suite/innodb_gis/t/create_spatial_index.test
+++ b/mysql-test/suite/innodb_gis/t/create_spatial_index.test
@@ -1143,7 +1143,6 @@ insert into `t1` values(
linestring(point(1,1),point(1,1))
);
-# --error ER_GIS_INVALID_DATA
--error ER_BAD_NULL_ERROR
insert into `t1` values
(
diff --git a/mysql-test/suite/innodb_gis/t/gis.test b/mysql-test/suite/innodb_gis/t/gis.test
index 44aec76770a..629bb94b8c5 100644
--- a/mysql-test/suite/innodb_gis/t/gis.test
+++ b/mysql-test/suite/innodb_gis/t/gis.test
@@ -1,4 +1,4 @@
-# This is a testcase copied from mysql-test/t/gis.test
+# This is a testcase copied from mysql-test/main/gis.test
--source include/have_innodb.inc
-- source include/have_geometry.inc
@@ -388,7 +388,6 @@ insert into t1 values (1.11);
--error 1416
insert into t1 values ("qwerty");
--error 1048
-# --error ER_GIS_INVALID_DATA
insert into t1 values (ST_pointfromtext('point(1,1)'));
drop table t1;
@@ -431,7 +430,6 @@ select
ST_y(b) IS NULL
from t1;
-# --error ER_GIS_INVALID_DATA
select
MBRwithin(b, b) IS NULL, MBRcontains(b, b) IS NULL, MBRoverlaps(b, b) IS NULL,
MBRequals(b, b) IS NULL, MBRdisjoint(b, b) IS NULL, ST_touches(b, b) IS NULL,
@@ -460,7 +458,6 @@ DROP TABLE t1;
#
CREATE TABLE `t1` ( `col9` set('a'), `col89` date);
INSERT IGNORE INTO `t1` VALUES ('','0000-00-00');
-# --error ER_GIS_INVALID_DATA
select ST_geomfromtext(col9,col89) as a from t1;
DROP TABLE t1;
@@ -617,17 +614,11 @@ SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS MBRwithin FROM t1 a1 JOIN
# MBROverlaps needs a few more tests, with point and line dimensions
-# --error ER_GIS_INVALID_DATA
SET @vert1 = ST_GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
-# --error ER_GIS_INVALID_DATA
SET @horiz1 = ST_GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
-# --error ER_GIS_INVALID_DATA
SET @horiz2 = ST_GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
-# --error ER_GIS_INVALID_DATA
SET @horiz3 = ST_GeomFromText('POLYGON ((2 0, 3 0, 2 0))');
-# --error ER_GIS_INVALID_DATA
SET @point1 = ST_GeomFromText('POLYGON ((0 0))');
-# --error ER_GIS_INVALID_DATA
SET @point2 = ST_GeomFromText('POLYGON ((-2 0))');
SELECT GROUP_CONCAT(a1.name ORDER BY a1.name) AS MBRoverlaps FROM t1 a1 WHERE MBROverlaps(a1.square, @vert1) GROUP BY a1.name;
@@ -767,10 +758,8 @@ SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUA
--echo # BUG#51875: crash when loading data into geometry function ST_polyfromwkb
--echo #
SET @a=0x00000000030000000100000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440;
-# --error ER_GIS_INVALID_DATA
SET @a=ST_POLYFROMWKB(@a);
SET @a=0x00000000030000000000000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440;
-# --error ER_GIS_INVALID_DATA
SET @a=ST_POLYFROMWKB(@a);
@@ -903,7 +892,6 @@ DROP TABLE g1;
CREATE TABLE g1(a TEXT NOT NULL, KEY(a(255)));
INSERT INTO g1 VALUES ('a'),('a');
-# --error ER_GIS_INVALID_DATA
SELECT 1 FROM g1 WHERE a >= ANY
(SELECT 1 FROM g1 WHERE a = ST_geomfromtext('') OR a) ;
@@ -1442,6 +1430,5 @@ DROP DATABASE gis_ogs;
--echo # Bug#13362660 ASSERTION `FIELD_POS < FIELD_COUNT' FAILED. IN PROTOCOL_TEXT::STORE
--echo #
-# --error ER_GIS_INVALID_DATA
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT ST_Union('', ''), md5(1);
diff --git a/mysql-test/suite/innodb_gis/t/precise.test b/mysql-test/suite/innodb_gis/t/precise.test
index 08b7e348362..3ddfc9369a4 100644
--- a/mysql-test/suite/innodb_gis/t/precise.test
+++ b/mysql-test/suite/innodb_gis/t/precise.test
@@ -122,7 +122,6 @@ SELECT ST_Equals(ST_PointFromText('POINT (12 13)'),ST_PointFromText('POINT (12 1
--echo # BUG#11759650/51979: UNION/INTERSECTION OF POLYGONS CRASHES MYSQL
--echo #
-# --error ER_GIS_INVALID_DATA
SELECT ST_ASTEXT(ST_UNION(ST_GEOMFROMTEXT('POLYGON((525000 183300,525400
183300,525400 18370, 525000 183700,525000 183300))'),
ST_geomfromtext('POLYGON((525298.67 183511.53,525296.57
diff --git a/mysql-test/suite/innodb_gis/t/rtree.test b/mysql-test/suite/innodb_gis/t/rtree.test
index 58d81576b3e..98931e70e62 100644
--- a/mysql-test/suite/innodb_gis/t/rtree.test
+++ b/mysql-test/suite/innodb_gis/t/rtree.test
@@ -78,17 +78,11 @@ SELECT name, ST_AsText(square) from t1 where MBRWithin(@p, square);
# MBROverlaps needs a few more tests, with point and line dimensions
-# --error ER_GIS_INVALID_DATA
SET @vert1 = ST_GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
-# --error ER_GIS_INVALID_DATA
SET @horiz1 = ST_GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
-# --error ER_GIS_INVALID_DATA
SET @horiz2 = ST_GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
-# --error ER_GIS_INVALID_DATA
SET @horiz3 = ST_GeomFromText('POLYGON ((2 0, 3 0, 2 0))');
-# --error ER_GIS_INVALID_DATA
SET @point1 = ST_GeomFromText('POLYGON ((0 0))');
-# --error ER_GIS_INVALID_DATA
SET @point2 = ST_GeomFromText('POLYGON ((-2 0))');
SELECT GROUP_CONCAT(a1.name ORDER BY a1.name) AS MBRoverlaps FROM t1 a1 WHERE MBROverlaps(a1.square, @vert1) GROUP BY a1.name;
diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result
index c207744fba5..0f63b2600e3 100644
--- a/mysql-test/suite/plugins/r/server_audit.result
+++ b/mysql-test/suite/plugins/r/server_audit.result
@@ -219,6 +219,10 @@ create procedure pr1() insert into test.t1 values ("foo", 42);
create function fn1(i int) returns int deterministic return i+1;
drop procedure pr1;
drop function fn1;
+create procedure pr1() insert into test.t1 values ("foo", 42);
+create function fn1(i int) returns int deterministic return i+1;
+drop procedure pr1;
+drop function fn1;
set global server_audit_events='table';
set global server_audit_incl_users='user1';
create user user1@localhost;
diff --git a/mysql-test/suite/plugins/t/server_audit.test b/mysql-test/suite/plugins/t/server_audit.test
index 382fc781b66..2c5acfad7ca 100644
--- a/mysql-test/suite/plugins/t/server_audit.test
+++ b/mysql-test/suite/plugins/t/server_audit.test
@@ -152,6 +152,10 @@ insert into t1 values (1), (2);
select * from t1;
select 2;
drop table t1;
+create procedure pr1() insert into test.t1 values ("foo", 42);
+create function fn1(i int) returns int deterministic return i+1;
+drop procedure pr1;
+drop function fn1;
create procedure pr1() insert into test.t1 values ("foo", 42);
create function fn1(i int) returns int deterministic return i+1;
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index 5b7f6c4c2ea..68134aca664 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -99,7 +99,6 @@ INSTALL(FILES
${CMAKE_CURRENT_SOURCE_DIR}/mysql_test_db.sql
${CMAKE_CURRENT_SOURCE_DIR}/fill_help_tables.sql
${CMAKE_CURRENT_SOURCE_DIR}/mysql_test_data_timezone.sql
- ${CMAKE_CURRENT_SOURCE_DIR}/mysql_to_mariadb.sql
${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp.sql
${CMAKE_CURRENT_BINARY_DIR}/maria_add_gis_sp_bootstrap.sql
${FIX_PRIVILEGES_SQL}
diff --git a/scripts/mysql_to_mariadb.sql b/scripts/mysql_to_mariadb.sql
deleted file mode 100644
index 4ee3f3a4214..00000000000
--- a/scripts/mysql_to_mariadb.sql
+++ /dev/null
@@ -1,22 +0,0 @@
--- Script that changes MySQL 5.7 privilege tables to MariaDB 10.x
--- This should be run first with
--- mysql --force mysql < mysql_to_mariadb.sql
--- It's ok to ignore any errors, as these usually means that the tables are
--- already fixed.
-
--- After this script s run, one should run at least:
--- mysql_upgrade --upgrade-system-tables
--- to get the other tables in the mysql database fixed.
-
--- Drop not existing columnms
-alter table mysql.user drop column `password_last_changed`, drop column `password_lifetime`, drop column `account_locked`;
-
--- Change existing columns
-alter table mysql.user change column `authentication_string` `auth_string` text COLLATE utf8_bin NOT NULL;
-
--- Add new columns
-alter table mysql.user add column `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '' after `user`, add column `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N' after `auth_string`;
-alter table mysql.user add column `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', add column `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000';
-
--- Fix passwords
-update mysql.user set `password`=`auth_string`, plugin='' where plugin="mysql_native_password";
diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh
index 91f9831af1c..1eb3811a120 100644
--- a/scripts/wsrep_sst_mariabackup.sh
+++ b/scripts/wsrep_sst_mariabackup.sh
@@ -867,10 +867,10 @@ then
fi
if [ -n "${WSREP_SST_OPT_PSWD:-}" ]; then
- INNOEXTRA+=" --password=$WSREP_SST_OPT_PSWD"
+ export MYSQL_PWD=$WSREP_SST_OPT_PSWD
elif [[ $usrst -eq 1 ]];then
- # Empty password, used for testing, debugging etc.
- INNOEXTRA+=" --password="
+ # Empty password, used for testing, debugging etc.
+ unset MYSQL_PWD
fi
get_keys
diff --git a/sql/item_create.cc b/sql/item_create.cc
index eb361b8222f..48e396210a5 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
- Copyright (c) 2008-2011 Monty Program Ab
+ Copyright (c) 2008, 2021, MariaDB Corporation.
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
@@ -109,7 +109,6 @@ public:
@return An item representing the function call
*/
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2) = 0;
-
protected:
/** Constructor. */
Create_func_arg2() {}
@@ -136,7 +135,6 @@ public:
@return An item representing the function call
*/
virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3) = 0;
-
protected:
/** Constructor. */
Create_func_arg3() {}
@@ -908,6 +906,19 @@ class Create_func_distance : public Create_func_arg2
Create_func_distance() {}
virtual ~Create_func_distance() {}
};
+
+
+class Create_func_distance_sphere: public Create_native_func
+{
+ public:
+ Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list);
+ static Create_func_distance_sphere s_singleton;
+
+ protected:
+ Create_func_distance_sphere() {}
+ virtual ~Create_func_distance_sphere() {}
+};
+
#endif
@@ -4840,6 +4851,26 @@ Create_func_glength::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_glength(thd, arg1);
}
+
+
+Create_func_distance_sphere Create_func_distance_sphere::s_singleton;
+
+Item*
+Create_func_distance_sphere::create_native(THD *thd, LEX_CSTRING *name,
+ List<Item> *item_list)
+{
+ int arg_count= 0;
+
+ if (item_list != NULL)
+ arg_count= item_list->elements;
+
+ if (arg_count < 2)
+ {
+ my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
+ return NULL;
+ }
+ return new (thd->mem_root) Item_func_sphere_distance(thd, *item_list);
+}
#endif
@@ -7343,6 +7374,7 @@ static Native_func_registry func_array[] =
{ { STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_within)},
{ { STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)},
{ { STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)},
+ { { C_STRING_WITH_LEN("ST_DISTANCE_SPHERE") }, GEOM_BUILDER(Create_func_distance_sphere)},
{ { STRING_WITH_LEN("SUBSTR_ORACLE") },
BUILDER(Create_func_substr_oracle)},
{ { STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)},
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 20ac6f0c88c..f2cc2e61b96 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -136,7 +136,7 @@ String *Item_func_geometry_from_json::val_str(String *str)
{
String *sv= args[1]->val_str(&tmp_js);
my_error(ER_WRONG_VALUE_FOR_TYPE, MYF(0),
- "option", sv->c_ptr_safe(), "ST_GeometryFromJSON");
+ "option", sv->c_ptr_safe(), "ST_GeomFromGeoJSON");
null_value= 1;
return 0;
}
@@ -173,7 +173,7 @@ String *Item_func_geometry_from_json::val_str(String *str)
code= ER_GEOJSON_NOT_CLOSED;
break;
case Geometry::GEOJ_DIMENSION_NOT_SUPPORTED:
- my_error(ER_GIS_INVALID_DATA, MYF(0), "ST_GeometryFromJSON");
+ my_error(ER_GIS_INVALID_DATA, MYF(0), "ST_GeomFromGeoJSON");
break;
default:
report_json_error_ex(js, &je, func_name(), 0, Sql_condition::WARN_LEVEL_WARN);
@@ -2528,11 +2528,151 @@ mem_error:
}
+double Item_func_sphere_distance::val_real()
+{
+ /* To test null_value of item, first get well-known bytes as a backups */
+ String bak1, bak2;
+ String *arg1= args[0]->val_str(&bak1);
+ String *arg2= args[1]->val_str(&bak2);
+ double distance= 0.0;
+ double sphere_radius= 6370986.0; // Default radius equals Earth radius
+
+ null_value= (args[0]->null_value || args[1]->null_value);
+ if (null_value)
+ {
+ return 0;
+ }
+
+ if (arg_count == 3)
+ {
+ sphere_radius= args[2]->val_real();
+ // Radius cannot be Null
+ if (args[2]->null_value)
+ {
+ null_value= true;
+ return 0;
+ }
+ if (sphere_radius <= 0)
+ {
+ my_error(ER_INTERNAL_ERROR, MYF(0), "Radius must be greater than zero.");
+ return 1;
+ }
+ }
+ Geometry_buffer buffer1, buffer2;
+ Geometry *g1, *g2;
+ if (!(g1= Geometry::construct(&buffer1, arg1->ptr(), arg1->length())) ||
+ !(g2= Geometry::construct(&buffer2, arg2->ptr(), arg2->length())))
+ {
+ my_error(ER_GIS_INVALID_DATA, MYF(0), "ST_Distance_Sphere");
+ goto handle_errors;
+ }
+// Method allowed for points and multipoints
+ if (!(g1->get_class_info()->m_type_id == Geometry::wkb_point ||
+ g1->get_class_info()->m_type_id == Geometry::wkb_multipoint) ||
+ !(g2->get_class_info()->m_type_id == Geometry::wkb_point ||
+ g2->get_class_info()->m_type_id == Geometry::wkb_multipoint))
+ {
+ // Generate error message in case different geometry is used?
+ my_error(ER_INTERNAL_ERROR, MYF(0), func_name());
+ return 0;
+ }
+ distance= spherical_distance_points(g1, g2, sphere_radius);
+ if (distance < 0)
+ {
+ my_error(ER_INTERNAL_ERROR, MYF(0), "Returned distance cannot be negative.");
+ return 1;
+ }
+ return distance;
+
+ handle_errors:
+ return 0;
+}
+
+
+double Item_func_sphere_distance::spherical_distance_points(Geometry *g1,
+ Geometry *g2,
+ const double r)
+{
+ double res= 0.0;
+ // Length for the single point (25 Bytes)
+ uint32 len= SRID_SIZE + POINT_DATA_SIZE + WKB_HEADER_SIZE;
+ int error= 0;
+
+ switch (g2->get_class_info()->m_type_id)
+ {
+ case Geometry::wkb_point:
+ // Optimization for point-point case
+ if (g1->get_class_info()->m_type_id == Geometry::wkb_point)
+ {
+ res= static_cast<Gis_point *>(g2)->calculate_haversine(g1, r, &error);
+ }
+ else
+ {
+ // Optimization for single point in Multipoint
+ if (g1->get_data_size() == len)
+ {
+ res= static_cast<Gis_point *>(g2)->calculate_haversine(g1, r, &error);
+ }
+ else
+ {
+ // There are multipoints in g1
+ // g1 is MultiPoint and calculate MP.sphericaldistance from g2 Point
+ if (g1->get_data_size() != GET_SIZE_ERROR)
+ static_cast<Gis_point *>(g2)->spherical_distance_multipoints(
+ (Gis_multi_point *)g1, r, &res, &error);
+ }
+ }
+ break;
+
+ case Geometry::wkb_multipoint:
+ // Optimization for point-point case
+ if (g1->get_class_info()->m_type_id == Geometry::wkb_point)
+ {
+ // Optimization for single point in Multipoint g2
+ if (g2->get_data_size() == len)
+ {
+ res= static_cast<Gis_point *>(g1)->calculate_haversine(g2, r, &error);
+ }
+ else
+ {
+ if (g2->get_data_size() != GET_SIZE_ERROR)
+ // g1 is a point (casted to multi_point) and g2 multipoint
+ static_cast<Gis_point *>(g1)->spherical_distance_multipoints(
+ (Gis_multi_point *)g2, r, &res, &error);
+ }
+ }
+ else
+ {
+ // Multipoints in g1 and g2 - no optimization
+ static_cast<Gis_multi_point *>(g1)->spherical_distance_multipoints(
+ (Gis_multi_point *)g2, r, &res, &error);
+ }
+ break;
+
+ default:
+ DBUG_ASSERT(0);
+ break;
+ }
+
+ if (res < 0)
+ goto handle_error;
+
+ handle_error:
+ if (error > 0)
+ my_error(ER_STD_OUT_OF_RANGE_ERROR, MYF(0),
+ "Longitude should be [-180,180]", "ST_Distance_Sphere");
+ else if(error < 0)
+ my_error(ER_STD_OUT_OF_RANGE_ERROR, MYF(0),
+ "Latitude should be [-90,90]", "ST_Distance_Sphere");
+ return res;
+}
+
+
String *Item_func_pointonsurface::val_str(String *str)
{
Gcalc_operation_transporter trn(&func, &collector);
- DBUG_ENTER("Item_func_pointonsurface::val_real");
+ DBUG_ENTER("Item_func_pointonsurface::val_str");
DBUG_ASSERT(fixed == 1);
String *res= args[0]->val_str(&tmp_value);
Geometry_buffer buffer;
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index 24bed6aa3ca..75545b8e4f3 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -2,7 +2,7 @@
#define ITEM_GEOFUNC_INCLUDED
/* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
- Copyright (C) 2011, 2016, MariaDB
+ Copyright (C) 2011, 2021, MariaDB
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
@@ -934,6 +934,20 @@ public:
};
+class Item_func_sphere_distance: public Item_real_func
+{
+ double spherical_distance_points(Geometry *g1, Geometry *g2,
+ const double sphere_r);
+public:
+ Item_func_sphere_distance(THD *thd, List<Item> &list):
+ Item_real_func(thd, list) {}
+ double val_real();
+ const char *func_name() const { return "st_distance_sphere"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_sphere_distance>(thd, this); }
+};
+
+
class Item_func_pointonsurface: public Item_geometry_func_args_geometry
{
String tmp_value;
diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc
index 5439f13b3f4..79fb77e38d2 100644
--- a/sql/signal_handler.cc
+++ b/sql/signal_handler.cc
@@ -30,6 +30,11 @@
#define SIGNAL_FMT "signal %d"
#endif
+
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
+
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
@@ -51,7 +56,7 @@ extern const char *optimizer_switch_names[];
static inline void output_core_info()
{
/* proc is optional on some BSDs so it can't hurt to look */
-#ifdef HAVE_READLINK
+#if defined(HAVE_READLINK) && !defined(__APPLE__)
char buff[PATH_MAX];
ssize_t len;
int fd;
@@ -77,6 +82,13 @@ static inline void output_core_info()
my_close(fd, MYF(0));
}
#endif
+#elif defined(__APPLE__)
+ char buff[PATH_MAX];
+ size_t len = sizeof(buff);
+ if (sysctlbyname("kern.corefile", buff, &len, NULL, 0) == 0)
+ {
+ my_safe_printf_stderr("Core pattern: %.*s\n", (int) len, buff);
+ }
#else
char buff[80];
my_getwd(buff, sizeof(buff), 0);
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 84a05532532..2482a21bb5f 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -1032,6 +1032,119 @@ const Geometry::Class_info *Gis_point::get_class_info() const
}
+/**
+ Function to calculate haversine.
+ Taking as arguments Point and Multipoint geometries.
+ Multipoint geometry has to be single point only.
+ It is up to caller to ensure valid input.
+
+ @param g pointer to the Geometry
+ @param r sphere radius
+ @param error pointer describing the error in case of the boundary conditions
+
+ @return distance in case without error, it is caclulcated distance (non-negative),
+ in case error exist, negative value.
+*/
+double Gis_point::calculate_haversine(const Geometry *g,
+ const double sphere_radius,
+ int *error)
+{
+ DBUG_ASSERT(sphere_radius > 0);
+ double x1r, x2r, y1r, y2r, dlong, dlat, res;
+
+ // This check is done only for optimization purposes where we know it will
+ // be one and only one point in Multipoint
+ if (g->get_class_info()->m_type_id == Geometry::wkb_multipoint)
+ {
+ const char point_size= 4 + WKB_HEADER_SIZE + POINT_DATA_SIZE+1; //1 for the type
+ char point_temp[point_size];
+ memset(point_temp+4, Geometry::wkb_point, 1);
+ memcpy(point_temp+5, static_cast<const Gis_multi_point *>(g)->get_data_ptr()+5, 4);
+ memcpy(point_temp+4+WKB_HEADER_SIZE, g->get_data_ptr()+4+WKB_HEADER_SIZE,
+ POINT_DATA_SIZE);
+ point_temp[point_size-1]= '\0';
+ Geometry_buffer gbuff;
+ Geometry *gg= Geometry::construct(&gbuff, point_temp, point_size-1);
+ DBUG_ASSERT(gg);
+ if (static_cast<Gis_point *>(gg)->get_xy_radian(&x2r, &y2r))
+ DBUG_ASSERT(0);
+ }
+ else
+ {
+ if (static_cast<const Gis_point *>(g)->get_xy_radian(&x2r, &y2r))
+ DBUG_ASSERT(0);
+ }
+ if (this->get_xy_radian(&x1r, &y1r))
+ DBUG_ASSERT(0);
+ // Check boundary conditions: longitude[-180,180]
+ if (!((x2r >= -M_PI && x2r <= M_PI) && (x1r >= -M_PI && x1r <= M_PI)))
+ {
+ *error=1;
+ return -1;
+ }
+ // Check boundary conditions: lattitude[-90,90]
+ if (!((y2r >= -M_PI/2 && y2r <= M_PI/2) && (y1r >= -M_PI/2 && y1r <= M_PI/2)))
+ {
+ *error=-1;
+ return -1;
+ }
+ dlat= sin((y2r - y1r)/2)*sin((y2r - y1r)/2);
+ dlong= sin((x2r - x1r)/2)*sin((x2r - x1r)/2);
+ res= 2*sphere_radius*asin((sqrt(dlat + cos(y1r)*cos(y2r)*dlong)));
+ return res;
+}
+
+
+/**
+ Function that calculate spherical distance of Point from Multipoint geometries.
+ In case there is single point in Multipoint geometries calculate_haversine()
+ can handle such case. Otherwise, new geometry (Point) has to be constructed.
+
+ @param g pointer to the Geometry
+ @param r sphere radius
+ @param result pointer to the result
+ @param err pointer to the error obtained from calculate_haversin()
+
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+int Gis_point::spherical_distance_multipoints(Geometry *g, const double r,
+ double *result, int *err)
+{
+ uint32 num_of_points2;
+ // To find the minimum radius it cannot be greater than Earth radius
+ double res= 6370986.0;
+ double temp_res= 0.0;
+ const uint32 len= 4 + WKB_HEADER_SIZE + POINT_DATA_SIZE + 1;
+ char s[len];
+ g->num_geometries(&num_of_points2);
+ DBUG_ASSERT(num_of_points2 >= 1);
+ if (num_of_points2 == 1)
+ {
+ *result= this->calculate_haversine(g, r, err);
+ return 0;
+ }
+ for (uint32 i=1; i <= num_of_points2; i++)
+ {
+ Geometry_buffer buff_temp;
+ Geometry *temp;
+
+ // First 4 bytes are handled already, make sure to create a Point
+ memset(s + 4, Geometry::wkb_point, 1);
+ memcpy(s + 5, g->get_data_ptr() + 5, 4);
+ memcpy(s + 4 + WKB_HEADER_SIZE, g->get_data_ptr() + 4 + WKB_HEADER_SIZE*i +\
+ POINT_DATA_SIZE*(i-1), POINT_DATA_SIZE);
+ s[len-1]= '\0';
+ temp= Geometry::construct(&buff_temp, s, len);
+ DBUG_ASSERT(temp);
+ temp_res= this->calculate_haversine(temp, r, err);
+ if (res > temp_res)
+ res= temp_res;
+ }
+ *result= res;
+ return 0;
+}
/***************************** LineString *******************************/
uint32 Gis_line_string::get_data_size() const
@@ -2163,6 +2276,81 @@ const Geometry::Class_info *Gis_multi_point::get_class_info() const
}
+/**
+ Function that calculate spherical distance of Multipoints geometries.
+ In case there is single point in Multipoint geometries calculate_haversine()
+ can handle such case. Otherwise, new geometry (Point) has to be constructed.
+
+ @param g pointer to the Geometry
+ @param r sphere radius
+ @param result pointer to the result
+ @param err pointer to the error obtained from calculate_haversin()
+
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+int Gis_multi_point::spherical_distance_multipoints(Geometry *g, const double r,
+ double *result, int *err)
+{
+ const uint32 len= 4 + WKB_HEADER_SIZE + POINT_DATA_SIZE + 1;
+ // Check how many points are stored in Multipoints
+ uint32 num_of_points1, num_of_points2;
+ // To find the minimum radius it cannot be greater than Earth radius
+ double res= 6370986.0;
+
+ /* From Item_func_sphere_distance::spherical_distance_points,
+ we are sure that there will be multiple points and we have to construct
+ Point geometry and return the smallest result.
+ */
+ num_geometries(&num_of_points1);
+ DBUG_ASSERT(num_of_points1 >= 1);
+ g->num_geometries(&num_of_points2);
+ DBUG_ASSERT(num_of_points2 >= 1);
+
+ for (uint32 i=1; i <= num_of_points1; i++)
+ {
+ Geometry_buffer buff_temp;
+ Geometry *temp;
+ double temp_res= 0.0;
+ char s[len];
+ // First 4 bytes are handled already, make sure to create a Point
+ memset(s + 4, Geometry::wkb_point, 1);
+ memcpy(s + 5, this->get_data_ptr() + 5, 4);
+ memcpy(s + 4 + WKB_HEADER_SIZE, this->get_data_ptr() + 4 + WKB_HEADER_SIZE*i +\
+ POINT_DATA_SIZE*(i-1), POINT_DATA_SIZE);
+ s[len-1]= '\0';
+ temp= Geometry::construct(&buff_temp, s, len);
+ DBUG_ASSERT(temp);
+ // Optimization for single Multipoint
+ if (num_of_points2 == 1)
+ {
+ *result= static_cast<Gis_point *>(temp)->calculate_haversine(g, r, err);
+ return 0;
+ }
+ for (uint32 j=1; j<= num_of_points2; j++)
+ {
+ Geometry_buffer buff_temp2;
+ Geometry *temp2;
+ char s2[len];
+ // First 4 bytes are handled already, make sure to create a Point
+ memset(s2 + 4, Geometry::wkb_point, 1);
+ memcpy(s2 + 5, g->get_data_ptr() + 5, 4);
+ memcpy(s2 + 4 + WKB_HEADER_SIZE, g->get_data_ptr() + 4 + WKB_HEADER_SIZE*j +\
+ POINT_DATA_SIZE*(j-1), POINT_DATA_SIZE);
+ s2[len-1]= '\0';
+ temp2= Geometry::construct(&buff_temp2, s2, len);
+ DBUG_ASSERT(temp2);
+ temp_res= static_cast<Gis_point *>(temp)->calculate_haversine(temp2, r, err);
+ if (res > temp_res)
+ res= temp_res;
+ }
+ }
+ *result= res;
+ return 0;
+}
+
+
/***************************** MultiLineString *******************************/
uint32 Gis_multi_line_string::get_data_size() const
diff --git a/sql/spatial.h b/sql/spatial.h
index 55f450b1b1b..0c00482c09b 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -332,6 +332,11 @@ public:
m_data+= WKB_HEADER_SIZE;
}
+ const char *get_data_ptr() const
+ {
+ return m_data;
+ }
+
bool envelope(String *result) const;
static Class_info *ci_collection[wkb_last+1];
@@ -410,6 +415,17 @@ public:
return 0;
}
+ int get_xy_radian(double *x, double *y) const
+ {
+ if (!get_xy(x, y))
+ {
+ *x= (*x)*M_PI/180;
+ *y= (*y)*M_PI/180;
+ return 0;
+ }
+ return 1;
+ }
+
int get_x(double *x) const
{
if (no_data(m_data, SIZEOF_STORED_DOUBLE))
@@ -436,6 +452,10 @@ public:
}
int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
+ double calculate_haversine(const Geometry *g, const double sphere_radius,
+ int *error);
+ int spherical_distance_multipoints(Geometry *g, const double r, double *result,
+ int *error);
};
@@ -535,6 +555,8 @@ public:
}
int store_shapes(Gcalc_shape_transporter *trn) const;
const Class_info *get_class_info() const;
+ int spherical_distance_multipoints(Geometry *g, const double r, double *res,
+ int *error);
};
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index a9d5dbd91c9..5a5e73c5b1a 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -620,7 +620,7 @@ Next alarm time: %lu\n",
#if defined(HAVE_MALLINFO2)
struct mallinfo2 info = mallinfo2();
#elif defined(HAVE_MALLINFO)
- struct mallinfo info= mallinfo();
+ struct mallinfo info= mallinfo();
#endif
#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
char llbuff[10][22];
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 67077741d9b..ce798a918e3 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -2773,16 +2773,18 @@ extern "C" bool wsrep_thd_ignore_table(THD *thd)
extern int
wsrep_trx_order_before(THD *thd1, THD *thd2)
{
- if (wsrep_thd_trx_seqno(thd1) < wsrep_thd_trx_seqno(thd2)) {
- WSREP_DEBUG("BF conflict, order: %lld %lld\n",
- (long long)wsrep_thd_trx_seqno(thd1),
- (long long)wsrep_thd_trx_seqno(thd2));
- return 1;
- }
- WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n",
- (long long)wsrep_thd_trx_seqno(thd1),
- (long long)wsrep_thd_trx_seqno(thd2));
- return 0;
+ const longlong trx1_seqno= wsrep_thd_trx_seqno(thd1);
+ const longlong trx2_seqno= wsrep_thd_trx_seqno(thd2);
+ WSREP_DEBUG("BF conflict, order: %lld %lld\n",
+ trx1_seqno, trx2_seqno);
+
+ if (trx1_seqno == WSREP_SEQNO_UNDEFINED ||
+ trx2_seqno == WSREP_SEQNO_UNDEFINED)
+ return 1; /* trx is not yet replicated */
+ else if (trx1_seqno < trx2_seqno)
+ return 1;
+
+ return 0;
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 9bb1235cbbc..57d8f23b662 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -18873,23 +18873,28 @@ static void bg_wsrep_kill_trx(
if (thd) {
wsrep_thd_LOCK(thd);
- victim_trx = thd_to_trx(thd);
- lock_mutex_enter();
- trx_mutex_enter(victim_trx);
- wsrep_thd_UNLOCK(thd);
- if (victim_trx->id != arg->trx_id)
- {
- trx_mutex_exit(victim_trx);
- lock_mutex_exit();
- victim_trx = NULL;
+ victim_trx= thd_to_trx(thd);
+ /* Victim trx might not exist e.g. on MDL-conflict. */
+ if (victim_trx) {
+ lock_mutex_enter();
+ trx_mutex_enter(victim_trx);
+ if (victim_trx->id != arg->trx_id ||
+ victim_trx->state == TRX_STATE_COMMITTED_IN_MEMORY)
+ {
+ /* Victim was meanwhile rolled back or
+ committed */
+ lock_mutex_exit();
+ trx_mutex_exit(victim_trx);
+ goto no_victim;
+ }
+ } else {
+no_victim:
+ wsrep_thd_UNLOCK(thd);
+ /* find_thread_by_id() acquired THD::LOCK_kill_data */
wsrep_thd_kill_UNLOCK(thd);
+ goto ret;
}
- }
-
- if (!victim_trx) {
- /* it can happen that trx_id was meanwhile rolled back */
- DBUG_PRINT("wsrep", ("no thd for conflicting lock"));
- goto ret;
+ wsrep_thd_UNLOCK(thd);
}
WSREP_DEBUG("BF kill (" ULINTPF ", seqno: " INT64PF
@@ -19044,7 +19049,7 @@ static void bg_wsrep_kill_trx(
}
ret_awake:
- awake = true;
+ awake= true;
ret_unlock:
trx_mutex_exit(victim_trx);
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index ee57a493119..bd09f3b81ca 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -637,71 +637,81 @@ lock_rec_get_insert_intention(
return(lock->type_mode & LOCK_INSERT_INTENTION);
}
+#ifdef UNIV_DEBUG
#ifdef WITH_WSREP
-/** Check if both conflicting lock and other record lock are brute force
-(BF). This case is a bug so report lock information and wsrep state.
-@param[in] lock_rec1 conflicting waiting record lock or NULL
-@param[in] lock_rec2 other waiting record lock
-@param[in] trx1 lock_rec1 can be NULL, trx
+/** Check if both conflicting lock transaction and other transaction
+requesting record lock are brute force (BF). If they are check is
+this BF-BF wait correct and if not report BF wait and assert.
+
+@param[in] lock_rec other waiting record lock
+@param[in] trx trx requesting conflicting record lock
*/
-static void wsrep_assert_no_bf_bf_wait(
- const lock_t* lock_rec1,
- const lock_t* lock_rec2,
- const trx_t* trx1)
+static void wsrep_assert_no_bf_bf_wait(const lock_t *lock, const trx_t *trx)
{
- ut_ad(!lock_rec1 || lock_get_type_low(lock_rec1) == LOCK_REC);
- ut_ad(lock_get_type_low(lock_rec2) == LOCK_REC);
+ ut_ad(lock_get_type_low(lock) == LOCK_REC);
ut_ad(lock_mutex_own());
+ trx_t* lock_trx= lock->trx;
/* Note that we are holding lock_sys->mutex, thus we should
not acquire THD::LOCK_thd_data mutex below to avoid mutexing
order violation. */
- if (!trx1->is_wsrep() || !lock_rec2->trx->is_wsrep())
+ if (!trx->is_wsrep() || !lock_trx->is_wsrep())
return;
- if (UNIV_LIKELY(!wsrep_thd_is_BF(trx1->mysql_thd, FALSE)))
- return;
- if (UNIV_LIKELY(!wsrep_thd_is_BF(lock_rec2->trx->mysql_thd, FALSE)))
+ if (UNIV_LIKELY(!wsrep_thd_is_BF(trx->mysql_thd, FALSE))
+ || UNIV_LIKELY(!wsrep_thd_is_BF(lock_trx->mysql_thd, FALSE)))
return;
- /* if BF - BF order is honored, we can keep trx1 waiting for the lock */
- if (wsrep_trx_order_before(trx1->mysql_thd, lock_rec2->trx->mysql_thd))
+ ut_ad(trx->state == TRX_STATE_ACTIVE);
+
+ trx_mutex_enter(lock_trx);
+ const trx_state_t trx2_state= lock_trx->state;
+ trx_mutex_exit(lock_trx);
+
+ /* If transaction is already committed in memory or
+ prepared we should wait. When transaction is committed in
+ memory we held trx mutex, but not lock_sys->mutex. Therefore,
+ we could end here before transaction has time to do
+ lock_release() that is protected with lock_sys->mutex. */
+ switch (trx2_state) {
+ case TRX_STATE_COMMITTED_IN_MEMORY:
+ case TRX_STATE_PREPARED:
return;
+ case TRX_STATE_ACTIVE:
+ break;
+ default:
+ ut_ad("invalid state" == 0);
+ }
- /* avoiding BF-BF conflict assert, if victim is already aborting
- or rolling back for replaying
- */
- if (wsrep_trx_is_aborting(lock_rec2->trx->mysql_thd))
+ /* If BF - BF order is honored, i.e. trx already holding
+ record lock should be ordered before this new lock request
+ we can keep trx waiting for the lock. If conflicting
+ transaction is already aborting or rolling back for replaying
+ we can also let new transaction waiting. */
+ if (wsrep_trx_order_before(lock_trx->mysql_thd, trx->mysql_thd)
+ || wsrep_trx_is_aborting(lock_trx->mysql_thd))
return;
mtr_t mtr;
- if (lock_rec1) {
- ib::error() << "Waiting lock on table: "
- << lock_rec1->index->table->name
- << " index: "
- << lock_rec1->index->name()
- << " that has conflicting lock ";
- lock_rec_print(stderr, lock_rec1, mtr);
- }
-
ib::error() << "Conflicting lock on table: "
- << lock_rec2->index->table->name
+ << lock->index->table->name
<< " index: "
- << lock_rec2->index->name()
+ << lock->index->name()
<< " that has lock ";
- lock_rec_print(stderr, lock_rec2, mtr);
+ lock_rec_print(stderr, lock, mtr);
ib::error() << "WSREP state: ";
- wsrep_report_bf_lock_wait(trx1->mysql_thd,
- trx1->id);
- wsrep_report_bf_lock_wait(lock_rec2->trx->mysql_thd,
- lock_rec2->trx->id);
+ wsrep_report_bf_lock_wait(trx->mysql_thd,
+ trx->id);
+ wsrep_report_bf_lock_wait(lock_trx->mysql_thd,
+ lock_trx->id);
/* BF-BF wait is a bug */
ut_error;
}
#endif /* WITH_WSREP */
+#endif /* UNIV_DEBUG */
/*********************************************************************//**
Checks if a lock request for a new lock has to wait for request lock2.
@@ -824,9 +834,11 @@ lock_rec_has_to_wait(
return false;
}
- /* There should not be two conflicting locks that are
- brute force. If there is it is a bug. */
- wsrep_assert_no_bf_bf_wait(NULL, lock2, trx);
+ /* We very well can let bf to wait normally as other
+ BF will be replayed in case of conflict. For debug
+ builds we will do additional sanity checks to catch
+ unsupported bf wait if any. */
+ ut_d(wsrep_assert_no_bf_bf_wait(lock2, trx));
#endif /* WITH_WSREP */
return true;
@@ -1095,66 +1107,35 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */
#ifdef WITH_WSREP
-static
-void
-wsrep_kill_victim(
-/*==============*/
- const trx_t * const trx,
- const lock_t *lock)
+static void wsrep_kill_victim(const trx_t * const trx, const lock_t *lock)
{
ut_ad(lock_mutex_own());
- ut_ad(trx_mutex_own(lock->trx));
+ ut_ad(trx->is_wsrep());
+ trx_t* lock_trx = lock->trx;
+ ut_ad(trx_mutex_own(lock_trx));
+ ut_ad(lock_trx != trx);
- /* quit for native mysql */
- if (!trx->is_wsrep()) return;
+ if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE))
+ return;
- my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
- my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE);
- mtr_t mtr;
+ if (lock_trx->state == TRX_STATE_COMMITTED_IN_MEMORY
+ || lock_trx->lock.was_chosen_as_deadlock_victim)
+ return;
- if ((bf_this && !bf_other) ||
- (bf_this && bf_other && wsrep_trx_order_before(
- trx->mysql_thd, lock->trx->mysql_thd))) {
+ my_bool bf_other = wsrep_thd_is_BF(lock_trx->mysql_thd, FALSE);
- if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
- if (UNIV_UNLIKELY(wsrep_debug)) {
- ib::info() << "WSREP: BF victim waiting\n";
- }
+ if (!bf_other
+ || wsrep_trx_order_before(trx->mysql_thd,
+ lock_trx->mysql_thd)) {
+
+ if (lock_trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
+ if (UNIV_UNLIKELY(wsrep_debug))
+ WSREP_INFO("BF victim waiting");
/* cannot release lock, until our lock
is in the queue*/
- } else if (lock->trx != trx) {
- if (wsrep_log_conflicts) {
- if (bf_this) {
- ib::info() << "*** Priority TRANSACTION:";
- } else {
- ib::info() << "*** Victim TRANSACTION:";
- }
-
- trx_print_latched(stderr, trx, 3000);
-
- if (bf_other) {
- ib::info() << "*** Priority TRANSACTION:";
- } else {
- ib::info() << "*** Victim TRANSACTION:";
- }
- trx_print_latched(stderr, lock->trx, 3000);
-
- ib::info() << "*** WAITING FOR THIS LOCK TO BE GRANTED:";
-
- if (lock_get_type(lock) == LOCK_REC) {
- lock_rec_print(stderr, lock, mtr);
- } else {
- lock_table_print(stderr, lock);
- }
-
- ib::info() << " SQL1: "
- << wsrep_thd_query(trx->mysql_thd);
- ib::info() << " SQL2: "
- << wsrep_thd_query(lock->trx->mysql_thd);
- }
-
- wsrep_innobase_kill_one_trx(trx->mysql_thd,
- trx, lock->trx, TRUE);
+ } else {
+ wsrep_innobase_kill_one_trx(trx->mysql_thd, trx,
+ lock_trx, true);
}
}
}
@@ -2248,10 +2229,6 @@ static void lock_rec_dequeue_from_page(lock_t* in_lock)
/* Grant the lock */
ut_ad(lock->trx != in_lock->trx);
lock_grant(lock);
-#ifdef WITH_WSREP
- } else {
- wsrep_assert_no_bf_bf_wait(c, lock, c->trx);
-#endif /* WITH_WSREP */
}
}
} else {
@@ -4204,10 +4181,6 @@ released:
/* Grant the lock */
ut_ad(trx != lock->trx);
lock_grant(lock);
-#ifdef WITH_WSREP
- } else {
- wsrep_assert_no_bf_bf_wait(c, lock, c->trx);
-#endif /* WITH_WSREP */
}
}
} else {
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index 7b888cdecc1..0f9e309accb 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2020, MariaDB Corporation.
+Copyright (c) 2015, 2021, MariaDB Corporation.
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
@@ -3370,6 +3370,57 @@ struct fil_iterator_t {
byte* crypt_io_buffer; /*!< IO buffer when encrypted */
};
+
+/** InnoDB writes page by page when there is page compressed
+tablespace involved. It does help to save the disk space when
+punch hole is enabled
+@param iter Tablespace iterator
+@param write_request Request to write into the file
+@param offset offset of the file to be written
+@param writeptr buffer to be written
+@param n_bytes number of bytes to be written
+@param try_punch_only Try the range punch only because the
+ current range is full of empty pages
+@return DB_SUCCESS */
+static
+dberr_t fil_import_compress_fwrite(const fil_iterator_t &iter,
+ const IORequest &write_request,
+ os_offset_t offset,
+ const byte *writeptr,
+ ulint n_bytes,
+ bool try_punch_only=false)
+{
+ dberr_t err= os_file_punch_hole(iter.file, offset, n_bytes);
+ if (err != DB_SUCCESS || try_punch_only)
+ return err;
+
+ for (ulint j= 0; j < n_bytes; j+= srv_page_size)
+ {
+ /* Read the original data length from block and
+ safer to read FIL_PAGE_COMPRESSED_SIZE because it
+ is not encrypted*/
+ ulint n_write_bytes= srv_page_size;
+ if (j || offset)
+ {
+ n_write_bytes= mach_read_from_2(writeptr + j + FIL_PAGE_DATA);
+ const unsigned ptype= mach_read_from_2(writeptr + j + FIL_PAGE_TYPE);
+ /* Ignore the empty page */
+ if (ptype == 0 && n_write_bytes == 0)
+ continue;
+ n_write_bytes+= FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE;
+ if (ptype == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED)
+ n_write_bytes+= FIL_PAGE_COMPRESSION_METHOD_SIZE;
+ }
+
+ err= os_file_write(write_request, iter.filepath, iter.file,
+ writeptr + j, offset + j, n_write_bytes);
+ if (err != DB_SUCCESS)
+ break;
+ }
+
+ return err;
+}
+
/********************************************************************//**
TODO: This can be made parallel trivially by chunking up the file and creating
a callback per thread. . Main benefit will be to use multiple CPUs for
@@ -3411,7 +3462,10 @@ fil_iterate(
/* TODO: For ROW_FORMAT=COMPRESSED tables we do a lot of useless
copying for non-index pages. Unfortunately, it is
required by buf_zip_decompress() */
- dberr_t err = DB_SUCCESS;
+ dberr_t err = DB_SUCCESS;
+ bool page_compressed = false;
+ bool punch_hole = true;
+ IORequest write_request(IORequest::WRITE);
for (offset = iter.start; offset < iter.end; offset += n_bytes) {
if (callback.is_interrupted()) {
@@ -3489,9 +3543,8 @@ page_corrupted:
goto func_exit;
}
- const bool page_compressed
- = fil_page_is_compressed_encrypted(src)
- || fil_page_is_compressed(src);
+ page_compressed= fil_page_is_compressed_encrypted(src)
+ || fil_page_is_compressed(src);
if (page_compressed && block->page.zip.data) {
goto page_corrupted;
@@ -3646,13 +3699,23 @@ not_encrypted:
}
}
- /* A page was updated in the set, write back to disk. */
- if (updated) {
- IORequest write_request(IORequest::WRITE);
+ if (page_compressed && punch_hole) {
+ err = fil_import_compress_fwrite(
+ iter, write_request, offset, writeptr, n_bytes,
+ !updated);
- err = os_file_write(write_request,
- iter.filepath, iter.file,
- writeptr, offset, n_bytes);
+ if (err != DB_SUCCESS) {
+ punch_hole = false;
+ if (updated) {
+ goto normal_write;
+ }
+ }
+ } else if (updated) {
+ /* A page was updated in the set, write back to disk. */
+normal_write:
+ err = os_file_write(
+ write_request, iter.filepath, iter.file,
+ writeptr, offset, n_bytes);
if (err != DB_SUCCESS) {
goto func_exit;
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 7a9c2cd9240..0638465527c 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -3900,6 +3900,8 @@ row_merge_drop_indexes(
ut_ad(prev);
ut_a(table->fts);
fts_drop_index(table, index, trx);
+ row_merge_drop_index_dict(
+ trx, index->id);
/* We can remove a DICT_FTS
index from the cache, because
we do not allow ADD FULLTEXT INDEX
diff --git a/support-files/rpm/server-posttrans.sh b/support-files/rpm/server-posttrans.sh
index 1406c78a5f5..1525b592735 100644
--- a/support-files/rpm/server-posttrans.sh
+++ b/support-files/rpm/server-posttrans.sh
@@ -1,10 +1,15 @@
if [ -r %{restart_flag} ] ; then
rm %{restart_flag}
+ # only restart the server if it was alredy running
if [ -x /usr/bin/systemctl ] ; then
/usr/bin/systemctl daemon-reload > /dev/null 2>&1
- /usr/bin/systemctl try-restart mariadb.service > /dev/null 2>&1
+ if [ /usr/bin/systemctl is-active mysql ]; then
+ /usr/bin/systemctl restart mysql > /dev/null 2>&1
+ else
+ /usr/bin/systemctl try-restart mariadb.service > /dev/null 2>&1
+ fi
+ # not a systemd-enabled environment, use SysV startup script
elif %{_sysconfdir}/init.d/mysql status > /dev/null 2>&1; then
- # only restart the server if it was alredy running
- %{_sysconfdir}/init.d/mysql restart
+ %{_sysconfdir}/init.d/mysql restart > /dev/null 2>&1
fi
fi
diff --git a/tests/grant.pl b/tests/grant.pl
deleted file mode 100755
index b50481a93fc..00000000000
--- a/tests/grant.pl
+++ /dev/null
@@ -1,750 +0,0 @@
-#!/usr/bin/env perl
-
-# Copyright (c) 2000, 2005 MySQL AB, 2009 Sun Microsystems, Inc.
-# Use is subject to license terms.
-#
-# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
-
-#
-# Testing of grants.
-# Note that this will delete all table and column grants !
-#
-
-use DBI;
-use Getopt::Long;
-use strict;
-
-use vars qw($dbh $user_dbh $opt_help $opt_Information $opt_force $opt_debug
- $opt_verbose $opt_server $opt_root_user $opt_password $opt_user
- $opt_database $opt_host $version $user $tables_cols $columns_cols
- $tmp_table $opt_silent);
-
-$version="1.1";
-$opt_help=$opt_Information=$opt_force=$opt_debug=$opt_verbose=$opt_silent=0;
-$opt_host="localhost",
-$opt_server="mysql";
-$opt_root_user="root";
-$opt_password="";
-$opt_user="grant_user";
-$opt_database="grant_test";
-
-GetOptions("Information","help","server=s","root-user=s","password=s","user","database=s","force","host=s","debug","verbose","silent") || usage();
-usage() if ($opt_help || $opt_Information);
-
-$user="$opt_user\@$opt_host";
-
-if (!$opt_force)
-{
- print_info()
-}
-
-$|=1;
-
-$tables_cols="Host, Db, User, Table_name, Grantor, Table_priv, Column_priv";
-$columns_cols="Host, Db, User, Table_name, Column_name, Column_priv";
-$tmp_table="/tmp/mysql-grant.test"; # Can't use $$ as we are logging result
-unlink($tmp_table);
-
-#
-# clear grant tables
-#
-
-$dbh = DBI->connect("DBI:mysql:mysql:$opt_host",
- $opt_root_user,$opt_password,
- { PrintError => 0}) || die "Can't connect to mysql server with user '$opt_root_user': $DBI::errstr\n";
-
-safe_query("delete from user where user='$opt_user' or user='${opt_user}2'");
-safe_query("delete from db where user='$opt_user'");
-safe_query("delete from tables_priv");
-safe_query("delete from columns_priv");
-safe_query("lock tables mysql.user write"); # Test lock tables
-safe_query("flush privileges");
-safe_query("unlock tables"); # should already be unlocked
-safe_query("drop database $opt_database",3); # Don't print possible error
-safe_query("create database $opt_database");
-
-# check that the user can't login yet
-
-user_connect(1);
-#goto test;
-
-#
-# Enable column grant code
-#
-safe_query("grant select(user) on mysql.user to $user");
-safe_query("revoke select(user) on mysql.user from $user");
-
-#
-# Test grants on user level
-#
-
-safe_query("grant select on *.* to $user");
-safe_query("set password FOR ${opt_user}2\@$opt_host = password('test')",1);
-safe_query("set password FOR $opt_user\@$opt_host=password('test')");
-user_connect(1);
-safe_query("set password FOR $opt_user\@$opt_host=''");
-user_connect(0);
-user_query("select * from mysql.user where user = '$opt_user'");
-user_query("select * from mysql.db where user = '$opt_user'");
-safe_query("grant select on *.* to $user,$user");
-safe_query("show grants for $user");
-user_connect(0);
-
-# The following should fail
-user_query("insert into mysql.user (host,user) values ('error','$opt_user')",1);
-user_query("update mysql.user set host='error' WHERE user='$opt_user'",1);
-user_query("create table $opt_database.test (a int,b int)",1);
-user_query("grant select on *.* to ${opt_user}2\@$opt_host",1);
-safe_query("revoke select on $opt_database.test from $opt_user\@opt_host",1);
-safe_query("revoke select on $opt_database.* from $opt_user\@opt_host",1);
-safe_query("revoke select on *.* from $opt_user",1);
-safe_query("grant select on $opt_database.not_exists to $opt_user",1);
-safe_query("grant FILE on $opt_database.test to $opt_user",1);
-safe_query("grant select on *.* to wrong___________user_name",1);
-safe_query("grant select on $opt_database.* to wrong___________user_name",1);
-user_connect(0);
-user_query("grant select on $opt_database.test to $opt_user with grant option",1);
-safe_query("set password FOR ''\@''=''",1);
-user_query("set password FOR root\@$opt_host = password('test')",1);
-
-# Change privileges for user
-safe_query("revoke select on *.* from $user");
-safe_query("grant create,update on *.* to $user");
-user_connect(0);
-safe_query("flush privileges");
-user_query("create table $opt_database.test (a int,b int)");
-user_query("update $opt_database.test set b=b+1 where a > 0",1);
-safe_query("show grants for $user");
-safe_query("revoke update on *.* from $user");
-user_connect(0);
-safe_query("grant select(c) on $opt_database.test to $user",1);
-safe_query("revoke select(c) on $opt_database.test from $user",1);
-safe_query("grant select on $opt_database.test to wrong___________user_name",1);
-user_query("INSERT INTO $opt_database.test values (2,0)",1);
-
-safe_query("grant ALL PRIVILEGES on *.* to $user");
-safe_query("REVOKE INSERT on *.* from $user");
-user_connect(0);
-user_query("INSERT INTO $opt_database.test values (1,0)",1);
-safe_query("grant INSERT on *.* to $user");
-user_connect(0);
-user_query("INSERT INTO $opt_database.test values (2,0)");
-user_query("select count(*) from $opt_database.test");
-safe_query("revoke SELECT on *.* from $user");
-user_connect(0);
-user_query("select count(*) from $opt_database.test",1);
-user_query("INSERT INTO $opt_database.test values (3,0)");
-safe_query("grant SELECT on *.* to $user");
-user_connect(0);
-user_query("select count(*) from $opt_database.test");
-safe_query("revoke ALL PRIVILEGES on *.* from $user");
-user_connect(1);
-safe_query("delete from user where user='$opt_user'");
-safe_query("flush privileges");
-if (0) # Only if no anonymous user on localhost.
-{
- safe_query("grant select on *.* to $opt_user");
- user_connect(0);
- safe_query("revoke select on *.* from $opt_user");
- user_connect(1);
-}
-safe_query("delete from user where user='$opt_user'");
-safe_query("flush privileges");
-
-#
-# Test grants on database level
-#
-safe_query("grant select on $opt_database.* to $user");
-safe_query("select * from mysql.user where user = '$opt_user'");
-safe_query("select * from mysql.db where user = '$opt_user'");
-user_connect(0);
-user_query("select count(*) from $opt_database.test");
-# The following should fail
-user_query("select * from mysql.user where user = '$opt_user'",1);
-user_query("insert into $opt_database.test values (4,0)",1);
-user_query("update $opt_database.test set a=1",1);
-user_query("delete from $opt_database.test",1);
-user_query("create table $opt_database.test2 (a int)",1);
-user_query("ALTER TABLE $opt_database.test add c int",1);
-user_query("CREATE INDEX dummy ON $opt_database.test (a)",1);
-user_query("drop table $opt_database.test",1);
-user_query("grant ALL PRIVILEGES on $opt_database.* to ${opt_user}2\@$opt_host",1);
-
-# Change privileges for user
-safe_query("grant ALL PRIVILEGES on $opt_database.* to $user WITH GRANT OPTION");
-user_connect(0);
-user_query("insert into $opt_database.test values (5,0)");
-safe_query("REVOKE ALL PRIVILEGES on * from $user",1);
-safe_query("REVOKE ALL PRIVILEGES on *.* from $user");
-safe_query("REVOKE ALL PRIVILEGES on $opt_database.* from $user");
-safe_query("REVOKE ALL PRIVILEGES on $opt_database.* from $user");
-user_connect(0);
-user_query("insert into $opt_database.test values (6,0)",1);
-safe_query("REVOKE GRANT OPTION on $opt_database.* from $user");
-user_connect(1);
-safe_query("grant ALL PRIVILEGES on $opt_database.* to $user");
-
-user_connect(0);
-user_query("select * from mysql.user where user = '$opt_user'",1);
-user_query("insert into $opt_database.test values (7,0)");
-user_query("update $opt_database.test set a=3 where a=2");
-user_query("delete from $opt_database.test where a=3");
-user_query("create table $opt_database.test2 (a int not null)");
-user_query("alter table $opt_database.test2 add b int");
-user_query("create index dummy on $opt_database.test2 (a)");
-user_query("update test,test2 SET test.a=test2.a where test.a=test2.a");
-user_query("drop table $opt_database.test2");
-user_query("show tables from grant_test");
-# These should fail
-user_query("insert into mysql.user (host,user) values ('error','$opt_user',0)",1);
-
-# Revoke database privileges
-safe_query("revoke ALL PRIVILEGES on $opt_database.* from $user");
-safe_query("select * from mysql.user where user = '$opt_user'");
-safe_query("select * from mysql.db where user = '$opt_user'");
-
-# Test multi-updates
-safe_query("grant CREATE,UPDATE,DROP on $opt_database.* to $user");
-user_connect(0);
-user_query("create table $opt_database.test2 (a int not null)");
-user_query("update test,test2 SET test.a=1 where 1",1);
-user_query("update test,test2 SET test.a=test2.a where 1",1);
-safe_query("grant SELECT on $opt_database.* to $user");
-user_connect(0);
-user_query("update test,test2 SET test.a=test2.a where test2.a=test.a");
-user_query("drop table $opt_database.test2");
-
-# Revoke database privileges
-safe_query("revoke ALL PRIVILEGES on $opt_database.* from $user");
-user_connect(1);
-
-#
-# Test of grants on table level
-#
-
-safe_query("grant create on $opt_database.test2 to $user");
-user_connect(0);
-user_query("create table $opt_database.test2 (a int not null)");
-user_query("show tables"); # Should only show test, not test2
-user_query("show columns from test",1);
-user_query("show keys from test",1);
-user_query("show columns from test2");
-user_query("show keys from test2");
-user_query("select * from test",1);
-safe_query("grant insert on $opt_database.test to $user");
-user_query("show tables");
-user_query("insert into $opt_database.test values (8,0)");
-user_query("update $opt_database.test set b=1",1);
-safe_query("grant update on $opt_database.test to $user");
-user_query("update $opt_database.test set b=2");
-
-user_query("update $opt_database.test,test2 SET test.b=3",1);
-safe_query("grant select on $opt_database.test2 to $user");
-user_query("update $opt_database.test,test2 SET test.b=3");
-safe_query("revoke select on $opt_database.test2 from $user");
-
-user_query("delete from $opt_database.test",1);
-safe_query("grant delete on $opt_database.test to $user");
-user_query("delete from $opt_database.test where a=1",1);
-user_query("update $opt_database.test set b=3 where b=1",1);
-user_query("update $opt_database.test set b=b+1",1);
-user_query("update $opt_database.test,test2 SET test.a=test2.a",1);
-
-#
-# Test global SELECT privilege combined with table level privileges
-#
-
-safe_query("grant SELECT on *.* to $user");
-user_connect(0);
-user_query("update $opt_database.test set b=b+1");
-user_query("update $opt_database.test set b=b+1 where a > 0");
-user_query("update $opt_database.test,test2 SET test.a=test2.a");
-user_query("update $opt_database.test,test2 SET test2.a=test.a",1);
-safe_query("revoke SELECT on *.* from $user");
-safe_query("grant SELECT on $opt_database.* to $user");
-user_connect(0);
-user_query("update $opt_database.test set b=b+1");
-user_query("update $opt_database.test set b=b+1 where a > 0");
-safe_query("grant UPDATE on *.* to $user");
-user_connect(0);
-user_query("update $opt_database.test set b=b+1");
-user_query("update $opt_database.test set b=b+1 where a > 0");
-safe_query("revoke UPDATE on *.* from $user");
-safe_query("revoke SELECT on $opt_database.* from $user");
-user_connect(0);
-user_query("update $opt_database.test set b=b+1 where a > 0",1);
-user_query("update $opt_database.test set b=b+1",1);
-
-# Add one privilege at a time until the user has all privileges
-user_query("select * from test",1);
-safe_query("grant select on $opt_database.test to $user");
-user_query("delete from $opt_database.test where a=1");
-user_query("update $opt_database.test set b=2 where b=1");
-user_query("update $opt_database.test set b=b+1");
-user_query("select count(*) from test");
-user_query("update test,test2 SET test.b=4",1);
-user_query("update test,test2 SET test2.a=test.a",1);
-user_query("update test,test2 SET test.a=test2.a",1);
-
-user_query("create table $opt_database.test3 (a int)",1);
-user_query("alter table $opt_database.test2 add c int",1);
-safe_query("grant alter on $opt_database.test2 to $user");
-user_query("alter table $opt_database.test2 add c int");
-user_query("create index dummy ON $opt_database.test (a)",1);
-safe_query("grant index on $opt_database.test2 to $user");
-user_query("create index dummy ON $opt_database.test2 (a)");
-user_query("insert into test2 SELECT a,a from test",1);
-safe_query("grant insert on test2 to $user",1); # No table: mysql.test2
-safe_query("grant insert(a) on $opt_database.test2 to $user");
-user_query("insert into test2 SELECT a,a from test",1);
-safe_query("grant insert(c) on $opt_database.test2 to $user");
-user_query("insert into test2 SELECT a,a from test");
-user_query("select count(*) from test2,test",1);
-user_query("select count(*) from test,test2",1);
-user_query("replace into test2 SELECT a from test",1);
-safe_query("grant update on $opt_database.test2 to $user");
-user_query("update test,test2 SET test2.a=test.a");
-user_query("update test,test2 SET test.b=test2.a where 0",1);
-user_query("update test,test2 SET test.a=2 where test2.a>100",1);
-user_query("update test,test2 SET test.a=test2.a",1);
-user_query("replace into test2 SELECT a,a from test",1);
-safe_query("grant DELETE on $opt_database.test2 to $user");
-user_query("replace into test2 SELECT a,a from test");
-user_query("insert into test (a) SELECT a from test2",1);
-safe_query("grant SELECT on $opt_database.test2 to $user");
-user_query("update test,test2 SET test.b=test2.a where 0");
-user_query("update test,test2 SET test.a=test2.a where test2.a>100");
-
-safe_query("revoke UPDATE on $opt_database.test2 from $user");
-safe_query("grant UPDATE (c) on $opt_database.test2 to $user");
-user_query("update test,test2 SET test.b=test2.a where 0");
-user_query("update test,test2 SET test.a=test2.a where test2.a>100");
-user_query("update test,test2 SET test2.a=test2.a where test2.a>100",1);
-user_query("update test,test2 SET test2.c=test2.a where test2.a>100");
-
-safe_query("revoke SELECT,UPDATE on $opt_database.test2 from $user");
-safe_query("grant UPDATE on $opt_database.test2 to $user");
-
-user_query("drop table $opt_database.test2",1);
-user_query("grant select on $opt_database.test2 to $user with grant option",1);
-safe_query("grant drop on $opt_database.test2 to $user with grant option");
-user_query("grant drop on $opt_database.test2 to $user with grant option");
-user_query("grant select on $opt_database.test2 to $user with grant option",1);
-
-# check rename privileges
-user_query("rename table $opt_database.test2 to $opt_database.test3",1);
-safe_query("grant CREATE,DROP on $opt_database.test3 to $user");
-user_query("rename table $opt_database.test2 to $opt_database.test3",1);
-user_query("create table $opt_database.test3 (a int)");
-safe_query("grant INSERT on $opt_database.test3 to $user");
-user_query("drop table $opt_database.test3");
-user_query("rename table $opt_database.test2 to $opt_database.test3");
-user_query("rename table $opt_database.test3 to $opt_database.test2",1);
-safe_query("grant ALTER on $opt_database.test3 to $user");
-user_query("rename table $opt_database.test3 to $opt_database.test2");
-safe_query("revoke DROP on $opt_database.test2 from $user");
-user_query("rename table $opt_database.test2 to $opt_database.test3");
-user_query("drop table if exists $opt_database.test2,$opt_database.test3",1);
-safe_query("drop table if exists $opt_database.test2,$opt_database.test3");
-
-# Check that the user doesn't have some user privileges
-user_query("create database $opt_database",1);
-user_query("drop database $opt_database",1);
-user_query("flush tables",1);
-safe_query("flush privileges");
-
-safe_query("select $tables_cols from mysql.tables_priv");
-safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user");
-safe_query("revoke ALL PRIVILEGES on $opt_database.test2 from $user");
-safe_query("revoke ALL PRIVILEGES on $opt_database.test3 from $user");
-safe_query("revoke GRANT OPTION on $opt_database.test2 from $user");
-safe_query("select $tables_cols from mysql.tables_priv");
-user_query("select count(a) from test",1);
-
-#
-# Test some grants on column level
-#
-
-safe_query("grant create,update on $opt_database.test2 to $user");
-user_query("create table $opt_database.test2 (a int not null)");
-user_query("delete from $opt_database.test where a=2",1);
-user_query("delete from $opt_database.test where A=2",1);
-user_query("update test set b=5 where b>0",1);
-user_query("update test,test2 SET test.b=5 where b>0",1);
-
-safe_query("grant update(b),delete on $opt_database.test to $user");
-safe_query("revoke update(a) on $opt_database.test from $user",1);
-user_query("delete from $opt_database.test where a=2",1);
-user_query("update test set b=5 where b>0",1);
-safe_query("grant select(a),select(b) on $opt_database.test to $user");
-user_query("delete from $opt_database.test where a=2");
-user_query("delete from $opt_database.test where A=2");
-user_query("update test set b=5 where b>0");
-user_query("update test set a=11 where b>5",1);
-user_query("update test,test2 SET test.b=5 where b>0",1);
-user_query("update test,test2 SET test.a=11 where b>0",1);
-user_query("update test,test2 SET test.b=test2.a where b>0",1);
-user_query("update test,test2 SET test.b=11 where test2.a>0",1);
-user_query("select a,A from test");
-
-safe_query("select $tables_cols from mysql.tables_priv");
-safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user");
-safe_query("select $tables_cols from mysql.tables_priv");
-safe_query("revoke GRANT OPTION on $opt_database.test from $user",1);
-safe_query("drop table $opt_database.test2");
-safe_query("revoke create,update on $opt_database.test2 from $user");
-
-#
-# Test grants on database level
-#
-
-safe_query("grant select(a) on $opt_database.test to $user");
-user_query("show full columns from test");
-safe_query("grant insert (b), update (b) on $opt_database.test to $user");
-
-user_query("select count(a) from test");
-user_query("select count(skr.a) from test as skr");
-user_query("select count(a) from test where a > 5");
-user_query("insert into test (b) values (5)");
-user_query("insert into test (b) values (a)");
-user_query("update test set b=3 where a > 0");
-
-user_query("select * from test",1);
-user_query("select b from test",1);
-user_query("select a from test where b > 0",1);
-user_query("insert into test (a) values (10)",1);
-user_query("insert into test (b) values (b)",1);
-user_query("insert into test (a,b) values (1,5)",1);
-user_query("insert into test (b) values (1),(b)",1);
-user_query("update test set b=3 where b > 0",1);
-
-safe_query("select $tables_cols from mysql.tables_priv");
-safe_query("select $columns_cols from mysql.columns_priv");
-safe_query("revoke select(a), update (b) on $opt_database.test from $user");
-safe_query("select $tables_cols from mysql.tables_priv");
-safe_query("select $columns_cols from mysql.columns_priv");
-
-user_query("select count(a) from test",1);
-user_query("update test set b=4",1);
-
-safe_query("grant select(a,b), update (a,b) on $opt_database.test to $user");
-user_query("select count(a),count(b) from test where a+b > 0");
-user_query("insert into test (b) values (9)");
-user_query("update test set b=6 where b > 0");
-
-safe_query("flush privileges"); # Test restoring privileges from disk
-safe_query("select $tables_cols from mysql.tables_priv");
-safe_query("select $columns_cols from mysql.columns_priv");
-
-# Try mixing of table and database privileges
-
-user_query("insert into test (a,b) values (12,12)",1);
-safe_query("grant insert on $opt_database.* to $user");
-user_connect(0);
-user_query("insert into test (a,b) values (13,13)");
-
-# This grants and revokes SELECT on different levels.
-safe_query("revoke select(b) on $opt_database.test from $user");
-user_query("select count(a) from test where a+b > 0",1);
-user_query("update test set b=5 where a=2");
-safe_query("grant select on $opt_database.test to $user");
-user_connect(0);
-user_query("select count(a) from test where a+b > 0");
-safe_query("revoke select(b) on $opt_database.test from $user");
-user_query("select count(a) from test where a+b > 0");
-safe_query("revoke select on $opt_database.test from $user");
-user_connect(0);
-user_query("select count(a) from test where a+b > 0",1);
-safe_query("grant select(a) on $opt_database.test to $user");
-user_query("select count(a) from test where a+b > 0",1);
-safe_query("grant select on *.* to $user");
-user_connect(0);
-user_query("select count(a) from test where a+b > 0");
-safe_query("revoke select on *.* from $user");
-safe_query("grant select(b) on $opt_database.test to $user");
-user_connect(0);
-user_query("select count(a) from test where a+b > 0");
-
-
-safe_query("select * from mysql.db where user = '$opt_user'");
-safe_query("select $tables_cols from mysql.tables_priv where user = '$opt_user'");
-safe_query("select $columns_cols from mysql.columns_priv where user = '$opt_user'");
-
-safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user");
-user_query("select count(a) from test",1);
-user_query("select * from mysql.user order by hostname",1);
-safe_query("select * from mysql.db where user = '$opt_user'");
-safe_query("select $tables_cols from mysql.tables_priv where user = '$opt_user'");
-safe_query("select $columns_cols from mysql.columns_priv where user = '$opt_user'");
-
-#
-# Clear up privileges to make future tests easier
-
-safe_query("delete from user where user='$opt_user'");
-safe_query("delete from db where user='$opt_user'");
-safe_query("flush privileges");
-safe_query("show grants for $user",1);
-
-#
-# Test IDENTIFIED BY
-#
-
-safe_query("grant ALL PRIVILEGES on $opt_database.test to $user identified by 'dummy', ${opt_user}\@127.0.0.1 identified by 'dummy2'");
-user_connect(0,"dummy");
-safe_query("grant SELECT on $opt_database.* to $user identified by ''");
-user_connect(0);
-safe_query("revoke ALL PRIVILEGES on $opt_database.test from $user identified by '', ${opt_user}\@127.0.0.1 identified by 'dummy2'");
-safe_query("revoke ALL PRIVILEGES on $opt_database.* from $user identified by ''");
-
-safe_query("show grants for $user");
-
-#
-# Test bug reported in SELECT INTO OUTFILE
-#
-
-safe_query("create table $opt_database.test3 (a int, b int)");
-safe_query("grant SELECT on $opt_database.test3 to $user");
-safe_query("grant FILE on *.* to $user");
-safe_query("insert into $opt_database.test3 values (1,1)");
-user_connect(0);
-user_query("select * into outfile '$tmp_table' from $opt_database.test3");
-safe_query("revoke SELECT on $opt_database.test3 from $user");
-safe_query("grant SELECT(a) on $opt_database.test3 to $user");
-user_query("select a from $opt_database.test3");
-user_query("select * from $opt_database.test3",1);
-user_query("select a,b from $opt_database.test3",1);
-user_query("select b from $opt_database.test3",1);
-
-safe_query("revoke SELECT(a) on $opt_database.test3 from $user");
-safe_query("revoke FILE on *.* from $user");
-safe_query("drop table $opt_database.test3");
-
-#
-# Test privileges needed for LOCK TABLES
-#
-
-safe_query("create table $opt_database.test3 (a int)");
-user_connect(1);
-safe_query("grant INSERT on $opt_database.test3 to $user");
-user_connect(0);
-user_query("select * into outfile '$tmp_table' from $opt_database.test3",1);
-safe_query("grant SELECT on $opt_database.test3 to $user");
-user_connect(0);
-user_query("LOCK TABLES $opt_database.test3 READ",1);
-safe_query("grant LOCK TABLES on *.* to $user");
-safe_query("show grants for $user");
-safe_query("select * from mysql.user where user='$opt_user'");
-user_connect(0);
-user_query("LOCK TABLES $opt_database.test3 READ");
-user_query("UNLOCK TABLES");
-safe_query("revoke SELECT,INSERT,UPDATE,DELETE on $opt_database.test3 from $user");
-user_connect(0);
-safe_query("revoke LOCK TABLES on *.* from $user");
-user_connect(1);
-safe_query("drop table $opt_database.test3");
-
-#
-# test new privileges in 4.0.2
-#
-
-safe_query("show grants for $user");
-safe_query("grant all on *.* to $user WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 2 MAX_CONNECTIONS_PER_HOUR 3");
-safe_query("show grants for $user");
-safe_query("revoke LOCK TABLES on *.* from $user");
-safe_query("flush privileges");
-safe_query("show grants for $user");
-safe_query("revoke ALL PRIVILEGES on *.* from $user");
-safe_query("show grants for $user");
-
-#
-# Clean up things
-#
-
-unlink($tmp_table);
-safe_query("drop database $opt_database");
-safe_query("delete from user where user='$opt_user'");
-safe_query("delete from db where user='$opt_user'");
-safe_query("delete from tables_priv");
-safe_query("delete from columns_priv");
-safe_query("flush privileges");
-
-print "end of test\n";
-exit 0;
-
-sub usage
-{
- print <<EOF;
-$0 Ver $version
-
-This program tests that the GRANT commands works by creating a temporary
-database ($opt_database) and user ($opt_user).
-
-Options:
-
---database (Default $opt_database)
- In which database the test tables are created.
-
---force
- Don''t ask any question before starting this test.
-
---host='host name' (Default $opt_host)
- Host name where the database server is located.
-
---Information
---help
- Print this help
-
---password
- Password for root-user.
-
---server='server name' (Default $opt_server)
- Run the test on the given SQL server.
-
---user (Default $opt_user)
- A non-existing user on which we will test the GRANT commands.
-
---verbose
- Write all queries when we are execute them.
-
---root-user='user name' (Default $opt_root_user)
- User with privileges to modify the 'mysql' database.
-EOF
- exit(0);
-}
-
-
-sub print_info
-{
- my $tmp;
- print <<EOF;
-This test will clear your table and column grant table and recreate the
-$opt_database database !
-All privileges for $user will be destroyed !
-
-Don\'t run this test if you have done any GRANT commands that you want to keep!
-EOF
- for (;;)
- {
- print "Start test (yes/no) ? ";
- $tmp=<STDIN>; chomp($tmp); $tmp=lc($tmp);
- last if ($tmp =~ /^yes$/i);
- exit 1 if ($tmp =~ /^n/i);
- print "\n";
- }
-}
-
-
-sub user_connect
-{
- my ($ignore_error,$password)=@_;
- $password="" if (!defined($password));
-
- print "Connecting $opt_user\n" if ($opt_verbose);
- $user_dbh->disconnect if (defined($user_dbh));
-
- $user_dbh=DBI->connect("DBI:mysql:$opt_database:$opt_host",$opt_user,
- $password, { PrintError => 0});
- if (!$user_dbh)
- {
- if ($opt_verbose || !$ignore_error)
- {
- print "Error on connect: $DBI::errstr\n";
- }
- if (!$ignore_error)
- {
- die "The above should not have failed!";
- }
- }
- elsif ($ignore_error)
- {
- die "Connect succeeded when it shouldn't have !\n";
- }
-}
-
-sub safe_query
-{
- my ($query,$ignore_error)=@_;
- if (do_query($dbh,$query, $ignore_error))
- {
- if (!defined($ignore_error))
- {
- die "The above should not have failed!";
- }
- }
- elsif (defined($ignore_error) && $ignore_error == 1)
- {
- die "Query '$query' succeeded when it shouldn't have !\n";
- }
-}
-
-
-sub user_query
-{
- my ($query,$ignore_error)=@_;
- if (do_query($user_dbh,$query, $ignore_error))
- {
- if (!defined($ignore_error))
- {
- die "Query '$query' should not have failed!";
- }
- }
- elsif (defined($ignore_error) && $ignore_error == 1)
- {
- die "Query '$query' succeeded when it shouldn't have !\n";
- }
-}
-
-
-sub do_query
-{
- my ($my_dbh, $query, $ignore_error)=@_;
- my ($sth, $row, $tab, $col, $found, $fatal_error);
-
- print "$query\n" if ($opt_debug || $opt_verbose);
- if (!($sth= $my_dbh->prepare($query)))
- {
- print "Error in prepare: $DBI::errstr\n";
- return 1;
- }
- if (!$sth->execute)
- {
- $fatal_error= ($DBI::errstr =~ /parse error/);
- if (!$ignore_error || ($opt_verbose && $ignore_error != 3) || $fatal_error)
- {
- print "Error in execute: $DBI::errstr\n";
- }
- die if ($fatal_error);
- $sth->finish;
- return 1;
- }
- $found=0;
- if (!$opt_silent)
- {
- while (($row=$sth->fetchrow_arrayref))
- {
- $found=1;
- $tab="";
- foreach $col (@$row)
- {
- print $tab;
- print defined($col) ? $col : "NULL";
- $tab="\t";
- }
- print "\n";
- }
- print "\n" if ($found);
- }
- $sth->finish;
- return 0;
-}