mirror of
https://github.com/MariaDB/server.git
synced 2025-01-26 08:44:33 +01:00
Merge 10.3 into 10.4
This commit is contained in:
commit
50de71b026
35 changed files with 867 additions and 948 deletions
cmake/os
mysql-test
main
suite
plugin/server_audit
scripts
sql
storage/innobase
support-files/rpm
tests
|
@ -89,6 +89,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 "")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) ;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -140,6 +140,10 @@ select 2;
|
|||
2
|
||||
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;
|
||||
set global server_audit_events='query_ddl,query_dml';
|
||||
create table t1(id int);
|
||||
insert into t1 values (1), (2);
|
||||
|
@ -211,6 +215,14 @@ select 2;
|
|||
2
|
||||
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;
|
||||
drop procedure pr1;
|
||||
drop function fn1;
|
||||
set global server_audit_events='table';
|
||||
set global server_audit_incl_users='user1';
|
||||
create user user1@localhost;
|
||||
|
@ -406,6 +418,10 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv,
|
|||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop table t1',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create procedure pr1() insert into test.t1 values ("foo", 42)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create function fn1(i int) returns int deterministic return i+1',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop procedure pr1',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop function fn1',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'create table t1(id int)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'insert into t1 values (1), (2)',0
|
||||
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'select * from t1',0
|
||||
|
|
|
@ -107,6 +107,12 @@ select 2;
|
|||
/*! select 2*/;
|
||||
/*comment*/ 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;
|
||||
|
||||
set global server_audit_events='query_ddl,query_dml';
|
||||
create table t1(id int);
|
||||
insert into t1 values (1), (2);
|
||||
|
@ -146,6 +152,15 @@ 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;
|
||||
drop procedure pr1;
|
||||
drop function fn1;
|
||||
|
||||
set global server_audit_events='table';
|
||||
set global server_audit_incl_users='user1';
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
|
||||
#define PLUGIN_VERSION 0x104
|
||||
#define PLUGIN_STR_VERSION "1.4.11"
|
||||
#define PLUGIN_STR_VERSION "1.4.13"
|
||||
|
||||
#define _my_thread_var loc_thread_var
|
||||
|
||||
|
@ -859,12 +859,8 @@ struct sa_keyword keywords_to_skip[]=
|
|||
|
||||
struct sa_keyword not_ddl_keywords[]=
|
||||
{
|
||||
{4, "DROP", &function_word, SQLCOM_QUERY_ADMIN},
|
||||
{4, "DROP", &procedure_word, SQLCOM_QUERY_ADMIN},
|
||||
{4, "DROP", &user_word, SQLCOM_DCL},
|
||||
{6, "CREATE", &user_word, SQLCOM_DCL},
|
||||
{6, "CREATE", &function_word, SQLCOM_QUERY_ADMIN},
|
||||
{6, "CREATE", &procedure_word, SQLCOM_QUERY_ADMIN},
|
||||
{6, "RENAME", &user_word, SQLCOM_DCL},
|
||||
{0, NULL, 0, SQLCOM_DDL}
|
||||
};
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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";
|
|
@ -864,10 +864,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
|
||||
|
||||
check_extra
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008, 2020, MariaDB Corporation.
|
||||
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
|
||||
|
||||
|
||||
|
@ -4878,6 +4889,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
|
||||
|
||||
|
||||
|
@ -7457,6 +7488,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)},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
#define SIGNAL_FMT "signal %d"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
@ -52,7 +57,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;
|
||||
|
@ -78,6 +83,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);
|
||||
|
|
188
sql/spatial.cc
188
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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -18709,14 +18709,17 @@ static void bg_wsrep_kill_trx(void *void_arg)
|
|||
|
||||
lock_mutex_enter();
|
||||
trx_mutex_enter(victim_trx);
|
||||
if (victim_trx->id != arg->trx_id)
|
||||
if (victim_trx->id != arg->trx_id
|
||||
|| victim_trx->state == TRX_STATE_COMMITTED_IN_MEMORY)
|
||||
{
|
||||
/* apparently victim trx was meanwhile rolled back.
|
||||
tell bf thd not to wait, in case it already started to */
|
||||
/* Apparently victim trx was meanwhile rolled back or
|
||||
committed. Tell bf thd not to wait, in case it already
|
||||
started to. */
|
||||
trx_t *trx= thd_to_trx(bf_thd);
|
||||
/* note that bf_thd might not have trx e.g. in case of
|
||||
MDL-conflict. */
|
||||
if (lock_t *lock= (trx ? trx->lock.wait_lock : NULL)) {
|
||||
if (!trx) {
|
||||
/* bf_thd might not be associated with a
|
||||
transaction, in case of MDL conflict */
|
||||
} else if (lock_t *lock = trx->lock.wait_lock) {
|
||||
trx_mutex_enter(trx);
|
||||
lock_cancel_waiting_and_release(lock);
|
||||
trx_mutex_exit(trx);
|
||||
|
@ -18802,7 +18805,7 @@ and an open transaction on the node, not by a Galera writeset
|
|||
comparison as in the local certification failure.
|
||||
|
||||
@param[in] bf_thd Brute force (BF) thread
|
||||
@param[in,out] victim_trx Vimtim trx to be killed
|
||||
@param[in,out] victim_trx Transaction to be killed
|
||||
@param[in] signal Should victim be signaled */
|
||||
void
|
||||
wsrep_innobase_kill_one_trx(
|
||||
|
|
|
@ -637,75 +637,82 @@ 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_thd_order_before(trx1->mysql_thd, lock_rec2->trx->mysql_thd))
|
||||
return;
|
||||
ut_ad(trx->state == TRX_STATE_ACTIVE);
|
||||
|
||||
/* avoiding BF-BF conflict assert, if victim is already aborting
|
||||
or rolling back for replaying
|
||||
*/
|
||||
wsrep_thd_LOCK(lock_rec2->trx->mysql_thd);
|
||||
if (wsrep_thd_is_aborting(lock_rec2->trx->mysql_thd)) {
|
||||
wsrep_thd_UNLOCK(lock_rec2->trx->mysql_thd);
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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_thd_order_before(lock_trx->mysql_thd, trx->mysql_thd)
|
||||
|| wsrep_thd_is_aborting(lock_trx->mysql_thd)) {
|
||||
return;
|
||||
}
|
||||
wsrep_thd_UNLOCK(lock_rec2->trx->mysql_thd);
|
||||
|
||||
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.
|
||||
|
@ -828,9 +835,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;
|
||||
|
@ -1099,65 +1108,31 @@ 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)) {
|
||||
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE))
|
||||
return;
|
||||
}
|
||||
|
||||
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_other) ||
|
||||
(wsrep_thd_order_before(
|
||||
trx->mysql_thd, lock->trx->mysql_thd))) {
|
||||
|
||||
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
|
||||
if (UNIV_UNLIKELY(wsrep_debug)) {
|
||||
ib::info() << "WSREP: BF victim waiting\n";
|
||||
}
|
||||
if (!wsrep_thd_is_BF(lock_trx->mysql_thd, FALSE)
|
||||
|| wsrep_thd_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) {
|
||||
ib::info() << "*** Priority 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);
|
||||
}
|
||||
|
||||
} else {
|
||||
wsrep_innobase_kill_one_trx(trx->mysql_thd,
|
||||
lock->trx, true);
|
||||
lock_trx, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2251,10 +2226,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 {
|
||||
|
@ -4207,10 +4178,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 {
|
||||
|
|
|
@ -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
|
||||
|
@ -3351,6 +3351,55 @@ 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_ENCRYPT_COMP_METADATA_LEN;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -3396,7 +3445,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;
|
||||
const IORequest write_request(IORequest::WRITE);
|
||||
|
||||
for (offset = iter.start; offset < iter.end; offset += n_bytes) {
|
||||
if (callback.is_interrupted()) {
|
||||
|
@ -3474,7 +3526,7 @@ page_corrupted:
|
|||
src + FIL_PAGE_SPACE_ID);
|
||||
}
|
||||
|
||||
const bool page_compressed =
|
||||
page_compressed =
|
||||
(full_crc32
|
||||
&& fil_space_t::is_compressed(
|
||||
callback.get_space_flags())
|
||||
|
@ -3667,13 +3719,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;
|
||||
|
|
|
@ -3895,6 +3895,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
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
if [ -r %{restart_flag} ] ; then
|
||||
rm %{restart_flag}
|
||||
# only restart the server if it was alredy running
|
||||
# only restart the server if it was already 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
|
||||
%{_sysconfdir}/init.d/mysql restart
|
||||
%{_sysconfdir}/init.d/mysql restart > /dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
|
|
750
tests/grant.pl
750
tests/grant.pl
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue