Merge 10.2 into 10.3

This commit is contained in:
Marko Mäkelä 2021-05-24 09:38:49 +03:00
commit 1864a8ea93
51 changed files with 1514 additions and 310 deletions

View File

@ -110,11 +110,13 @@ FOREACH(_base
ENDIF()
ENDFOREACH()
IF(NOT RPM AND NOT DEB)
FOREACH(tool gtar tar)
STRING(TOUPPER ${tool} TOOL)
FIND_PROGRAM(${TOOL}_EXECUTABLE ${tool} DOC "path to the executable")
MARK_AS_ADVANCED(${TOOL}_EXECUTABLE)
ENDFOREACH()
ENDIF()
FIND_PACKAGE(Git)

13
cmake/FindGit.cmake Normal file
View File

@ -0,0 +1,13 @@
if(GIT_EXECUTABLE)
set(GIT_FOUND TRUE)
return()
endif()
if(DEFINED GIT_EXECUTABLE)
set(GIT_FOUND FALSE)
return()
endif()
set(orig_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH})
unset(CMAKE_MODULE_PATH)
include(FindGit)
set(CMAKE_MODULE_PATH ${orig_CMAKE_MODULE_PATH})

View File

@ -1,4 +1,9 @@
if(JAVA_AWT_LIBRARY)
set(JNI_FOUND TRUE)
return()
endif()
if(DEFINED JAVA_AWT_LIBRARY)
set(JNI_FOUND FALSE)
return()
endif()

View File

@ -1,4 +1,9 @@
if(Java_JAVA_EXECUTABLE)
set(JAVA_FOUND TRUE)
return()
endif()
if(DEFINED Java_JAVA_EXECUTABLE)
set(JAVA_FOUND FALSE)
return()
endif()

View File

@ -88,6 +88,12 @@ ENDIF()
SET(WITH_INNODB_SNAPPY OFF CACHE STRING "")
SET(WITH_NUMA 0 CACHE BOOL "")
SET(CPU_LEVEL1_DCACHE_LINESIZE 0)
IF(NOT EXISTS ${CMAKE_SOURCE_DIR}/.git)
SET(GIT_EXECUTABLE GIT_EXECUTABLE-NOTFOUND CACHE FILEPATH "")
ENDIF()
IF(WIN32)
SET(INSTALL_MYSQLTESTDIR "" CACHE STRING "")
SET(INSTALL_SQLBENCHDIR "" CACHE STRING "")

View File

@ -124,8 +124,6 @@ SET(ignored
"%ignore ${CMAKE_INSTALL_PREFIX}/share/man"
"%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man1"
"%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man8"
"%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man1*"
"%ignore ${CMAKE_INSTALL_PREFIX}/share/man/man8*"
"%ignore ${CMAKE_INSTALL_PREFIX}/share/pkgconfig"
)

View File

@ -15,6 +15,8 @@
# Symbols with information about the CPU.
IF(NOT DEFINED CPU_LEVEL1_DCACHE_LINESIZE)
IF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
FIND_PROGRAM(SYSCTL sysctl)
MARK_AS_ADVANCED(SYSCTL)
@ -37,3 +39,5 @@ ELSE()
)
ENDIF()
ENDIF()
ENDIF()

View File

@ -29,7 +29,7 @@ IF(NOT CMAKE_CROSSCOMPILING)
TARGET_LINK_LIBRARIES(factorial dbug)
ENDIF()
IF(NOT WIN32 AND NOT CMAKE_GENERATOR MATCHES Xcode)
IF(NOT WIN32 AND NOT CMAKE_GENERATOR MATCHES Xcode AND NOT RPM AND NOT DEB)
FIND_PROGRAM(GROFF groff)
FIND_PROGRAM(NROFF nroff)
MARK_AS_ADVANCED(GROFF)

View File

@ -1,2 +1,6 @@
etc/mysql/conf.d/connect.cnf etc/mysql/mariadb.conf.d
usr/lib/mysql/plugin/ha_connect.so
usr/share/mysql/Mongo2.jar
usr/share/mysql/Mongo3.jar
usr/share/mysql/JavaWrappers.jar
usr/share/mysql/JdbcInterface.jar

View File

@ -1120,10 +1120,10 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
5 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
NULL UNION RESULT <union2,5> ALL NULL NULL NULL NULL NULL NULL
6 UNION <derived9> ALL NULL NULL NULL NULL 14 100.00
9 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
12 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
NULL UNION RESULT <union9,12> ALL NULL NULL NULL NULL NULL NULL
6 UNION <derived14> ALL NULL NULL NULL NULL 14 100.00
14 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
11 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
NULL UNION RESULT <union14,11> ALL NULL NULL NULL NULL NULL NULL
NULL UNION RESULT <union1,6> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 with cte_e as (with cte_o as (with cte_i as (/* select#4 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)/* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1 union /* select#5 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1)/* select#1 */ select `cte_e1`.`a` AS `a` from `cte_e` `cte_e1` where `cte_e1`.`a` > 1 union /* select#6 */ select `cte_e2`.`a` AS `a` from `cte_e` `cte_e2`
@ -1763,6 +1763,207 @@ a c
2 1
7 3
drop table t1;
#
# MDEV-23886: Stored Function returning the result of a query
# that uses CTE over a table twice
#
create table t1 (c1 int);
insert into t1 values (1),(2),(6);
create function f1() returns int return
( with cte1 as (select c1 from t1)
select sum(c1) from
(select * from cte1 union all select * from cte1) dt
);
select f1();
f1()
18
create function f2() returns int return
( with cte1 as (select c1 from t1)
select sum(s.c1) from cte1 as s, cte1 as t where s.c1=t.c1
);
select f2();
f2()
9
create function f3() returns int return
( with cte1 as (select c1 from t1)
select
case
when exists(select 1 from cte1 where c1 between 1 and 2) then 1
when exists(select 1 from cte1 where c1 between 5 and 6) then 2
else 0
end
);
select f3();
f3()
1
create view v1 as (select c1 from t1);
create function f4() returns int return
( select sum(c1) from
(select * from v1 union all select * from v1) dt
);
select f4();
f4()
18
create function f5() returns int return
( select sum(s.c1) from v1 as s, v1 as t where s.c1=t.c1
);
select f5();
f5()
9
create view v2(s) as
with cte1 as (select c1 from t1)
select sum(c1) from (select * from cte1 union all select * from cte1) dt;
create function f6() returns int return
(select s from v2);
select f6();
f6()
18
create function f7() returns int return
( select r.s from v2 as r, v2 as t where r.s=t.s
);
select f7();
f7()
18
select f5() + f6();
f5() + f6()
27
prepare stmt from "select f5() + f6();";
execute stmt;
f5() + f6()
27
execute stmt;
f5() + f6()
27
deallocate prepare stmt;
drop function f1;
drop function f2;
drop function f3;
drop function f4;
drop function f5;
drop function f6;
drop function f7;
drop view v1;
drop view v2;
create table t2 (a int, b int);
insert into t2
with cte1 as (select c1 from t1)
select * from cte1 as s, cte1 as t where s.c1=t.c1 and s.c1 > 5;
select * from t2;
a b
6 6
create procedure p1()
begin
insert into t2
with cte1 as (select c1 from t1)
select * from cte1 as s, cte1 as t where s.c1=t.c1 and s.c1 <= 2 and t.c1 >= 2;
end |
call p1();
select * from t2;
a b
6 6
2 2
drop procedure p1;
# checking CTE resolution for queries with hanging CTEs
with
cte1(a) as (select * from t1 where c1 <= 2),
cte2(b) as (select * from cte1 where a >= 2),
cte3 as (select * from cte1,cte2 where cte1.a < cte2.b)
select * from cte3;
a b
1 2
select * from t2;
a b
6 6
2 2
with
cte1(a) as (select * from t1 where c1 <= 2),
cte2(b) as (select * from cte1 where a >= 2),
cte3 as (select * from cte1,cte2 where cte1.a < cte2.b)
select * from t2;
a b
6 6
2 2
with
cte1(a) as (select * from t1 where c1 <= 2),
cte2(b) as (select * from cte1 where c1 >= 2),
cte3 as (select * from cte1,cte2 where cte1.a < cte2.b)
select * from t2;
ERROR 42S22: Unknown column 'c1' in 'where clause'
with
cte1(a) as (select * from t1 where c1 <= 2),
cte2(b) as (select * from cte1 where a >= 2),
cte3 as (select * from cte1,cte2 where cte1.a < cte2.c1)
select * from t2;
ERROR 42S22: Unknown column 'cte2.c1' in 'where clause'
with
cte1 as (select * from t1 where c1 <= 2),
cte2(a,b) as (select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select * from cte2;
a b
1 1
2 2
with
cte1 as (select * from t1 where c1 <= 2),
cte2(a,b) as (select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select * from t2;
a b
6 6
2 2
with
cte1 as (select * from t1 where c1 <= 2),
cte2(a,b) as (select * from cte1 as s1, cte1 as s2 where s1.c1=c1)
select * from t2;
ERROR 23000: Column 'c1' in where clause is ambiguous
with cte3 as
( with cte2(a,b) as
( with cte1 as (select * from t1 where c1 <= 2)
select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select r1.a,r2.b from cte2 as r1, cte2 as r2)
select * from cte3;
a b
1 1
2 1
1 2
2 2
with cte3 as
( with cte2(a,b) as
( with cte1 as (select * from t1 where c1 <= 2)
select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select r1.a,r2.b from cte2 as r1, cte2 as r2)
select * from t2;
a b
6 6
2 2
with cte3 as
( with cte2(a,b) as
( with cte1 as (select * from t1 where c1 <= 2)
select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select r1.c1,r2.c1 from cte2 as r1, cte2 as r2)
select * from t2;
ERROR 42S22: Unknown column 'r1.c1' in 'field list'
create procedure p1()
begin
insert into t2
with cte1 as (select c1 from t1)
select * from t1 as s, t1 as t where s.c1=t.c1 and s.c1 <= 2 and t.c1 >= 2;
end |
call p1();
select * from t2;
a b
6 6
2 2
2 2
drop procedure p1;
create procedure p1()
begin
insert into t2
with cte1 as (select a from t1)
select * from t1 as s, t1 as t where s.c1=t.c1 and s.c1 <= 2 and t.c1 >= 2;
end |
call p1();
ERROR 42S22: Unknown column 'a' in 'field list'
drop procedure p1;
drop table t1,t2;
# End of 10.2 tests
#
# MDEV-21673: several references to CTE that uses

View File

@ -1261,6 +1261,208 @@ select a, c from cte as r2 where a > 4;
drop table t1;
--echo #
--echo # MDEV-23886: Stored Function returning the result of a query
--echo # that uses CTE over a table twice
--echo #
create table t1 (c1 int);
insert into t1 values (1),(2),(6);
create function f1() returns int return
( with cte1 as (select c1 from t1)
select sum(c1) from
(select * from cte1 union all select * from cte1) dt
);
select f1();
create function f2() returns int return
( with cte1 as (select c1 from t1)
select sum(s.c1) from cte1 as s, cte1 as t where s.c1=t.c1
);
select f2();
create function f3() returns int return
( with cte1 as (select c1 from t1)
select
case
when exists(select 1 from cte1 where c1 between 1 and 2) then 1
when exists(select 1 from cte1 where c1 between 5 and 6) then 2
else 0
end
);
select f3();
create view v1 as (select c1 from t1);
create function f4() returns int return
( select sum(c1) from
(select * from v1 union all select * from v1) dt
);
select f4();
create function f5() returns int return
( select sum(s.c1) from v1 as s, v1 as t where s.c1=t.c1
);
select f5();
create view v2(s) as
with cte1 as (select c1 from t1)
select sum(c1) from (select * from cte1 union all select * from cte1) dt;
create function f6() returns int return
(select s from v2);
select f6();
create function f7() returns int return
( select r.s from v2 as r, v2 as t where r.s=t.s
);
select f7();
select f5() + f6();
prepare stmt from "select f5() + f6();";
execute stmt;
execute stmt;
deallocate prepare stmt;
drop function f1;
drop function f2;
drop function f3;
drop function f4;
drop function f5;
drop function f6;
drop function f7;
drop view v1;
drop view v2;
create table t2 (a int, b int);
insert into t2
with cte1 as (select c1 from t1)
select * from cte1 as s, cte1 as t where s.c1=t.c1 and s.c1 > 5;
select * from t2;
delimiter |;
create procedure p1()
begin
insert into t2
with cte1 as (select c1 from t1)
select * from cte1 as s, cte1 as t where s.c1=t.c1 and s.c1 <= 2 and t.c1 >= 2;
end |
delimiter ;|
call p1();
select * from t2;
drop procedure p1;
--echo # checking CTE resolution for queries with hanging CTEs
with
cte1(a) as (select * from t1 where c1 <= 2),
cte2(b) as (select * from cte1 where a >= 2),
cte3 as (select * from cte1,cte2 where cte1.a < cte2.b)
select * from cte3;
select * from t2;
with
cte1(a) as (select * from t1 where c1 <= 2),
cte2(b) as (select * from cte1 where a >= 2),
cte3 as (select * from cte1,cte2 where cte1.a < cte2.b)
select * from t2;
--error ER_BAD_FIELD_ERROR
with
cte1(a) as (select * from t1 where c1 <= 2),
cte2(b) as (select * from cte1 where c1 >= 2),
cte3 as (select * from cte1,cte2 where cte1.a < cte2.b)
select * from t2;
--error ER_BAD_FIELD_ERROR
with
cte1(a) as (select * from t1 where c1 <= 2),
cte2(b) as (select * from cte1 where a >= 2),
cte3 as (select * from cte1,cte2 where cte1.a < cte2.c1)
select * from t2;
with
cte1 as (select * from t1 where c1 <= 2),
cte2(a,b) as (select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select * from cte2;
with
cte1 as (select * from t1 where c1 <= 2),
cte2(a,b) as (select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select * from t2;
--error ER_NON_UNIQ_ERROR
with
cte1 as (select * from t1 where c1 <= 2),
cte2(a,b) as (select * from cte1 as s1, cte1 as s2 where s1.c1=c1)
select * from t2;
with cte3 as
( with cte2(a,b) as
( with cte1 as (select * from t1 where c1 <= 2)
select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select r1.a,r2.b from cte2 as r1, cte2 as r2)
select * from cte3;
with cte3 as
( with cte2(a,b) as
( with cte1 as (select * from t1 where c1 <= 2)
select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select r1.a,r2.b from cte2 as r1, cte2 as r2)
select * from t2;
--error ER_BAD_FIELD_ERROR
with cte3 as
( with cte2(a,b) as
( with cte1 as (select * from t1 where c1 <= 2)
select * from cte1 as s1, cte1 as s2 where s1.c1=s2.c1)
select r1.c1,r2.c1 from cte2 as r1, cte2 as r2)
select * from t2;
delimiter |;
create procedure p1()
begin
insert into t2
with cte1 as (select c1 from t1)
select * from t1 as s, t1 as t where s.c1=t.c1 and s.c1 <= 2 and t.c1 >= 2;
end |
delimiter ;|
call p1();
select * from t2;
drop procedure p1;
delimiter |;
create procedure p1()
begin
insert into t2
with cte1 as (select a from t1)
select * from t1 as s, t1 as t where s.c1=t.c1 and s.c1 <= 2 and t.c1 >= 2;
end |
delimiter ;|
--error ER_BAD_FIELD_ERROR
call p1();
drop procedure p1;
drop table t1,t2;
--echo # End of 10.2 tests
--echo #

View File

@ -22,9 +22,40 @@ SELECT @a:=CONVERT('aя' USING filename) AS `@a`, BINARY @a, REVERSE(@a), HEX(@a
@a BINARY @a REVERSE(@a) HEX(@a) HEX(REVERSE(@a))
aя a@r1 яa 61407231 40723161
#
# Beginning of 10.2 test.
#
# MDEV-25462: Assertion `m_status == DA_ERROR || m_status == DA_OK ||
# m_status == DA_OK_BULK' failed in Diagnostics_area::message from
# get_schema_tables_record
#
SELECT @@character_set_client, @@character_set_connection, @@character_set_results;
@@character_set_client @@character_set_connection @@character_set_results
utf8 utf8 utf8
SET @old_character_set_client= @@character_set_client;
SET @old_character_set_connection= @@character_set_connection;
SET @old_character_set_results= @@character_set_results;
SET NAMES 'filename';
ERROR 42000: Variable 'character_set_client' can't be set to the value of 'filename'
SELECT @@character_set_client, @@character_set_connection, @@character_set_results;
@@character_set_client @@character_set_connection @@character_set_results
utf8 utf8 utf8
CREATE VIEW v2 AS SELECT 1;
SHOW TABLE STATUS;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
v2 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL VIEW NULL NULL
DROP VIEW v2;
SET @@character_set_client= @old_character_set_client;
SET @@character_set_connection= @old_character_set_connection;
SET @@character_set_results= @old_character_set_results;
#
# End of 10.2 test
#
#
# MDEV-22022 Various mangled SQL statements will crash 10.3 to 10.5 debug builds
#
SET CHARACTER_SET_CLIENT=17;
ERROR 42000: Variable 'character_set_client' can't be set to the value of '17'
SELECT doc.`Children`.0 FROM t1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?Children??0?FROM?t1' at line 1
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.0 FROM t1' at line 1
SET NAMES latin1;
# End of 10.3 tests

View File

@ -28,12 +28,40 @@ select convert(convert(',' using filename) using binary);
SET NAMES utf8;
SELECT @a:=CONVERT('aя' USING filename) AS `@a`, BINARY @a, REVERSE(@a), HEX(@a), HEX(REVERSE(@a));
--echo #
--echo # Beginning of 10.2 test.
--echo #
--echo # MDEV-25462: Assertion `m_status == DA_ERROR || m_status == DA_OK ||
--echo # m_status == DA_OK_BULK' failed in Diagnostics_area::message from
--echo # get_schema_tables_record
--echo #
SELECT @@character_set_client, @@character_set_connection, @@character_set_results;
SET @old_character_set_client= @@character_set_client;
SET @old_character_set_connection= @@character_set_connection;
SET @old_character_set_results= @@character_set_results;
--error ER_WRONG_VALUE_FOR_VAR
SET NAMES 'filename';
SELECT @@character_set_client, @@character_set_connection, @@character_set_results;
CREATE VIEW v2 AS SELECT 1;
SHOW TABLE STATUS;
DROP VIEW v2;
SET @@character_set_client= @old_character_set_client;
SET @@character_set_connection= @old_character_set_connection;
SET @@character_set_results= @old_character_set_results;
--echo #
--echo # End of 10.2 test
--echo #
--echo #
--echo # MDEV-22022 Various mangled SQL statements will crash 10.3 to 10.5 debug builds
--echo #
--error ER_WRONG_VALUE_FOR_VAR
SET CHARACTER_SET_CLIENT=17;
--error ER_PARSE_ERROR
SELECT doc.`Children`.0 FROM t1;
SET NAMES latin1;
--echo # End of 10.3 tests

View File

@ -1468,7 +1468,7 @@ lc-messages-dir MYSQL_SHAREDIR/
lc-time-names en_US
local-infile TRUE
lock-wait-timeout 86400
log-bin (No default value)
log-bin foo
log-bin-compress FALSE
log-bin-compress-min-len 256
log-bin-index (No default value)

View File

@ -11,7 +11,7 @@
# force symbolic-links=0 (valgrind build has a different default)
#
exec $MYSQLD_BOOTSTRAP_CMD --symbolic-links=0 --lower-case-table-names=1 --help --verbose > $MYSQL_TMP_DIR/mysqld--help.txt 2>&1;
exec $MYSQLD_BOOTSTRAP_CMD --symbolic-links=0 --log-bin=foo --lower-case-table-names=1 --help --verbose > $MYSQL_TMP_DIR/mysqld--help.txt 2>&1;
# The inline perl code below will copy $MYSQL_TMP_DIR/mysqld--help.txt
# to output, but filter away some variable stuff (e.g. paths).

View File

@ -2721,7 +2721,15 @@ id select_type table type possible_keys key key_len ref rows Extra
SELECT a FROM t1 WHERE (a, a) IN (SELECT 1, 2) AND a = (SELECT MIN(b) FROM t2);
a
DROP TABLE t1,t2;
# End of 10.2 tests
#
# MDEV-22462: Item_in_subselect::create_single_in_to_exists_cond(JOIN *, Item **, Item **): Assertion `false' failed.
#
select 1 from dual where 1 in (select 5 from dual where 1);
1
create table t1 (a int);
insert into t1 values (1),(2),(3);
update t1 set a = 2 where a in (select a from dual where a = a);
drop table t1;
#
# MDEV-18335: Assertion `!error || error == 137' failed in subselect_rowid_merge_engine::init
#
@ -2847,4 +2855,15 @@ INSERT INTO t2 VALUES (3),(4);
SELECT 1 IN (SELECT (SELECT a FROM t1) AS x FROM t2 GROUP BY x);
ERROR 21000: Subquery returns more than 1 row
drop table t1,t2;
#
# MDEV-25629: Crash in get_sort_by_table() in subquery with order by having outer ref
#
CREATE TABLE t1 (i1 int);
insert into t1 values (1),(2);
SELECT 1
FROM (t1 JOIN t1 AS ref_t1 ON
(t1.i1 > (SELECT ref_t1.i1 AS c0 FROM t1 b ORDER BY -c0)));
ERROR 21000: Subquery returns more than 1 row
DROP TABLE t1;
# End of 10.2 tests
# End of 10.3 tests

View File

@ -2236,7 +2236,17 @@ SELECT a FROM t1 WHERE (a, a) IN (SELECT 1, 2) AND a = (SELECT MIN(b) FROM t2);
DROP TABLE t1,t2;
--echo # End of 10.2 tests
--echo #
--echo # MDEV-22462: Item_in_subselect::create_single_in_to_exists_cond(JOIN *, Item **, Item **): Assertion `false' failed.
--echo #
select 1 from dual where 1 in (select 5 from dual where 1);
create table t1 (a int);
insert into t1 values (1),(2),(3);
update t1 set a = 2 where a in (select a from dual where a = a);
drop table t1;
--echo #
--echo # MDEV-18335: Assertion `!error || error == 137' failed in subselect_rowid_merge_engine::init
@ -2353,4 +2363,19 @@ INSERT INTO t2 VALUES (3),(4); # Optional, fails either way
SELECT 1 IN (SELECT (SELECT a FROM t1) AS x FROM t2 GROUP BY x);
drop table t1,t2;
--echo #
--echo # MDEV-25629: Crash in get_sort_by_table() in subquery with order by having outer ref
--echo #
CREATE TABLE t1 (i1 int);
insert into t1 values (1),(2);
--error ER_SUBQUERY_NO_1_ROW
SELECT 1
FROM (t1 JOIN t1 AS ref_t1 ON
(t1.i1 > (SELECT ref_t1.i1 AS c0 FROM t1 b ORDER BY -c0)));
DROP TABLE t1;
--echo # End of 10.2 tests
--echo # End of 10.3 tests

View File

@ -20,7 +20,7 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (f INT) ENGINE=INNODB
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (f INT) ENGINE=INNODB
DROP TABLE t1,t2;
FLUSH LOGS;
RESET MASTER;
#
# Kill OPTIMIZE command after table modification
#

View File

@ -56,7 +56,7 @@ SET debug_sync = 'reset';
--source include/show_binlog_events.inc
DROP TABLE t1,t2;
FLUSH LOGS;
RESET MASTER;
--echo #
--echo # Kill OPTIMIZE command after table modification
@ -81,6 +81,9 @@ eval KILL $thd_id;
SET debug_sync = 'reset';
--disconnect con1
--let $wait_binlog_event= OPTIMIZE
--source include/wait_for_binlog_event.inc
DROP TABLE t1,t2;
let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
FLUSH LOGS;

View File

@ -264,6 +264,18 @@ t1 CREATE TABLE `t1` (
`f1` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# MDEV-25271 Double free of table when inplace alter
# FTS add index fails
#
call mtr.add_suppression("InnoDB: Operating system error number .* in a file operation.");
call mtr.add_suppression("InnoDB: Error number .* means");
call mtr.add_suppression("InnoDB: Cannot create file");
call mtr.add_suppression("InnoDB: Failed to create");
CREATE TABLE t1(a TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL UNIQUE) ENGINE=InnoDB;
ALTER TABLE t1 ADD FULLTEXT(a), ALGORITHM=INPLACE;
ERROR HY000: Got error 11 "Resource temporarily unavailable" from storage engine InnoDB
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(3)) ENGINE=InnoDB;
ALTER TABLE t1 ADD FULLTEXT KEY(a), ADD COLUMN b VARCHAR(3), ADD FULLTEXT KEY(b);
DROP TABLE t1;

View File

@ -52,3 +52,16 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
#
# MDEV-25663 Double free of transaction during TRUNCATE
#
call mtr.add_suppression("InnoDB: \\(Too many concurrent transactions\\)");
SET DEBUG_DBUG='-d,ib_create_table_fail_too_many_trx';
CREATE TABLE t1 (b CHAR(12), FULLTEXT KEY(b)) engine=InnoDB;
SET @save_dbug= @@debug_dbug;
SET debug_dbug='+d,ib_create_table_fail_too_many_trx';
TRUNCATE t1;
ERROR HY000: Got error -1 "Internal error < 0 (Not system error)" from storage engine InnoDB
SET debug_dbug=@save_dbug;
DROP TABLE t1;
# End of 10.3 tests

View File

@ -0,0 +1 @@
--enable-plugin-innodb-sys-tables

View File

@ -319,6 +319,25 @@ ALTER TABLE t1 ADD FTS_DOC_ID INT UNSIGNED NOT NULL, ALGORITHM=INPLACE;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # MDEV-25271 Double free of table when inplace alter
--echo # FTS add index fails
--echo #
call mtr.add_suppression("InnoDB: Operating system error number .* in a file operation.");
call mtr.add_suppression("InnoDB: Error number .* means");
call mtr.add_suppression("InnoDB: Cannot create file");
call mtr.add_suppression("InnoDB: Failed to create");
let MYSQLD_DATADIR=`select @@datadir`;
CREATE TABLE t1(a TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL UNIQUE) ENGINE=InnoDB;
let $fts_aux_file= `select concat('FTS_',right(concat(repeat('0',16), lower(hex(TABLE_ID))),16),'_BEING_DELETED.ibd') FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test/t1'`;
write_file $MYSQLD_DATADIR/test/$fts_aux_file;
EOF
--error ER_GET_ERRNO
ALTER TABLE t1 ADD FULLTEXT(a), ALGORITHM=INPLACE;
DROP TABLE t1;
remove_file $MYSQLD_DATADIR/test/$fts_aux_file;
# Add more than one FTS index
CREATE TABLE t1 (a VARCHAR(3)) ENGINE=InnoDB;
ALTER TABLE t1 ADD FULLTEXT KEY(a), ADD COLUMN b VARCHAR(3), ADD FULLTEXT KEY(b);

View File

@ -83,3 +83,18 @@ ALTER TABLE t1 ADD bl INT AS (LENGTH(b)) VIRTUAL;
CHECK TABLE t1;
DROP TABLE t1;
--source include/wait_until_count_sessions.inc
--echo #
--echo # MDEV-25663 Double free of transaction during TRUNCATE
--echo #
call mtr.add_suppression("InnoDB: \\(Too many concurrent transactions\\)");
SET DEBUG_DBUG='-d,ib_create_table_fail_too_many_trx';
CREATE TABLE t1 (b CHAR(12), FULLTEXT KEY(b)) engine=InnoDB;
SET @save_dbug= @@debug_dbug;
SET debug_dbug='+d,ib_create_table_fail_too_many_trx';
--error ER_GET_ERRNO
TRUNCATE t1;
SET debug_dbug=@save_dbug;
DROP TABLE t1;
--echo # End of 10.3 tests

View File

@ -0,0 +1,119 @@
install soname 'auth_ed25519';
flush status;
flush hosts;
flush user_resources;
flush privileges;
select `User`, `Host` from mysql.`user` where `host` like '%\\%%';
User Host
select `User`, `Host` from mysql.`user` where `user` like '192.%';
User Host
select `User`, `Host` from mysql.`user` where `user` like '2001:%';
User Host
select `User`, `Host` from mysql.`user` where `user` like 'santa.claus.%';
User Host
create user plug1@'santa.claus.ipv4.example.com'
identified with ed25519 as 'foo';
create user plug2@'santa.claus.ipv4.example.com'
identified with ED25519 as 'vubFBzIrapbfHct1/J72dnUryz5VS7lA6XHH8sIx4TI';
set @saved_dbug = @@global.debug_dbug;
set global debug_dbug= "+d,vio_peer_addr_fake_ipv4,getnameinfo_fake_ipv4,getaddrinfo_fake_good_ipv4";
connect(127.0.0.1,plug1,foo,test,PORT,SOCKET);
connect con1, 127.0.0.1, plug1,foo,,$MASTER_MYPORT;
ERROR 28000: Access denied for user 'plug1'@'santa.claus.ipv4.example.com' (using password: NO)
"Dumping performance_schema.host_cache"
IP 192.0.2.4
HOST santa.claus.ipv4.example.com
HOST_VALIDATED YES
SUM_CONNECT_ERRORS 0
COUNT_HOST_BLOCKED_ERRORS 0
COUNT_NAMEINFO_TRANSIENT_ERRORS 0
COUNT_NAMEINFO_PERMANENT_ERRORS 0
COUNT_FORMAT_ERRORS 0
COUNT_ADDRINFO_TRANSIENT_ERRORS 0
COUNT_ADDRINFO_PERMANENT_ERRORS 0
COUNT_FCRDNS_ERRORS 0
COUNT_HOST_ACL_ERRORS 0
COUNT_NO_AUTH_PLUGIN_ERRORS 0
COUNT_AUTH_PLUGIN_ERRORS 1
COUNT_HANDSHAKE_ERRORS 0
COUNT_PROXY_USER_ERRORS 0
COUNT_PROXY_USER_ACL_ERRORS 0
COUNT_AUTHENTICATION_ERRORS 0
COUNT_SSL_ERRORS 0
COUNT_MAX_USER_CONNECTIONS_ERRORS 0
COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS 0
COUNT_DEFAULT_DATABASE_ERRORS 0
COUNT_INIT_CONNECT_ERRORS 0
COUNT_LOCAL_ERRORS 0
COUNT_UNKNOWN_ERRORS 0
FIRST_ERROR_SEEN set
LAST_ERROR_SEEN set
connect(127.0.0.1,plug2,bar,test,PORT,SOCKET);
connect con1, 127.0.0.1, plug2,bar,,$MASTER_MYPORT;
ERROR 28000: Access denied for user 'plug2'@'santa.claus.ipv4.example.com' (using password: YES)
"Dumping performance_schema.host_cache"
IP 192.0.2.4
HOST santa.claus.ipv4.example.com
HOST_VALIDATED YES
SUM_CONNECT_ERRORS 0
COUNT_HOST_BLOCKED_ERRORS 0
COUNT_NAMEINFO_TRANSIENT_ERRORS 0
COUNT_NAMEINFO_PERMANENT_ERRORS 0
COUNT_FORMAT_ERRORS 0
COUNT_ADDRINFO_TRANSIENT_ERRORS 0
COUNT_ADDRINFO_PERMANENT_ERRORS 0
COUNT_FCRDNS_ERRORS 0
COUNT_HOST_ACL_ERRORS 0
COUNT_NO_AUTH_PLUGIN_ERRORS 0
COUNT_AUTH_PLUGIN_ERRORS 1
COUNT_HANDSHAKE_ERRORS 0
COUNT_PROXY_USER_ERRORS 0
COUNT_PROXY_USER_ACL_ERRORS 0
COUNT_AUTHENTICATION_ERRORS 1
COUNT_SSL_ERRORS 0
COUNT_MAX_USER_CONNECTIONS_ERRORS 0
COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS 0
COUNT_DEFAULT_DATABASE_ERRORS 0
COUNT_INIT_CONNECT_ERRORS 0
COUNT_LOCAL_ERRORS 0
COUNT_UNKNOWN_ERRORS 0
FIRST_ERROR_SEEN set
LAST_ERROR_SEEN set
connect con1, 127.0.0.1, plug2,foo,,$MASTER_MYPORT;
select current_user();
current_user()
plug2@santa.claus.ipv4.example.com
disconnect con1;
connection default;
"Dumping performance_schema.host_cache"
IP 192.0.2.4
HOST santa.claus.ipv4.example.com
HOST_VALIDATED YES
SUM_CONNECT_ERRORS 0
COUNT_HOST_BLOCKED_ERRORS 0
COUNT_NAMEINFO_TRANSIENT_ERRORS 0
COUNT_NAMEINFO_PERMANENT_ERRORS 0
COUNT_FORMAT_ERRORS 0
COUNT_ADDRINFO_TRANSIENT_ERRORS 0
COUNT_ADDRINFO_PERMANENT_ERRORS 0
COUNT_FCRDNS_ERRORS 0
COUNT_HOST_ACL_ERRORS 0
COUNT_NO_AUTH_PLUGIN_ERRORS 0
COUNT_AUTH_PLUGIN_ERRORS 1
COUNT_HANDSHAKE_ERRORS 0
COUNT_PROXY_USER_ERRORS 0
COUNT_PROXY_USER_ACL_ERRORS 0
COUNT_AUTHENTICATION_ERRORS 1
COUNT_SSL_ERRORS 0
COUNT_MAX_USER_CONNECTIONS_ERRORS 0
COUNT_MAX_USER_CONNECTIONS_PER_HOUR_ERRORS 0
COUNT_DEFAULT_DATABASE_ERRORS 0
COUNT_INIT_CONNECT_ERRORS 0
COUNT_LOCAL_ERRORS 0
COUNT_UNKNOWN_ERRORS 0
FIRST_ERROR_SEEN set
LAST_ERROR_SEEN set
drop user plug1@'santa.claus.ipv4.example.com';
drop user plug2@'santa.claus.ipv4.example.com';
set @@global.debug_dbug = @saved_dbug;
uninstall plugin ed25519;

View File

@ -0,0 +1,53 @@
#
# Tests for the performance_schema host_cache.
#
# Test authorization with auth plugins.
# error reporting in:
# - column COUNT_AUTH_PLUGIN_ERRORS
# - column COUNT_PROXY_USER_ERRORS
# - column COUNT_PROXY_USER_ACL_ERRORS
source include/not_embedded.inc;
source include/have_debug.inc;
source include/have_perfschema.inc;
source include/have_plugin_auth.inc;
source include/have_hostname_cache.inc;
if (!$AUTH_ED25519_SO) {
skip No auth_ed25519 plugin;
}
install soname 'auth_ed25519';
# Enforce a clean state
source ../include/wait_for_pfs_thread_count.inc;
source ../include/hostcache_set_state.inc;
create user plug1@'santa.claus.ipv4.example.com'
identified with ed25519 as 'foo';
create user plug2@'santa.claus.ipv4.example.com'
identified with ED25519 as 'vubFBzIrapbfHct1/J72dnUryz5VS7lA6XHH8sIx4TI';
set @saved_dbug = @@global.debug_dbug;
set global debug_dbug= "+d,vio_peer_addr_fake_ipv4,getnameinfo_fake_ipv4,getaddrinfo_fake_good_ipv4";
replace_result $MASTER_MYPORT PORT $MASTER_MYSOCK SOCKET;
error ER_ACCESS_DENIED_ERROR;
connect con1, 127.0.0.1, plug1,foo,,$MASTER_MYPORT;
source ../include/hostcache_dump.inc;
replace_result $MASTER_MYPORT PORT $MASTER_MYSOCK SOCKET;
error ER_ACCESS_DENIED_ERROR;
connect con1, 127.0.0.1, plug2,bar,,$MASTER_MYPORT;
source ../include/hostcache_dump.inc;
connect con1, 127.0.0.1, plug2,foo,,$MASTER_MYPORT;
select current_user();
disconnect con1;
connection default;
source ../include/hostcache_dump.inc;
drop user plug1@'santa.claus.ipv4.example.com';
drop user plug2@'santa.claus.ipv4.example.com';
set @@global.debug_dbug = @saved_dbug;
uninstall plugin ed25519;

View File

@ -41,17 +41,17 @@ static int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
/* prepare the pk */
if (info->auth_string_length != PASSWORD_LEN)
return CR_AUTH_USER_CREDENTIALS;
return CR_ERROR; // bad password in the user table
memcpy(pw, info->auth_string, PASSWORD_LEN);
pw[PASSWORD_LEN]= '=';
if (my_base64_decode(pw, PASSWORD_LEN_BUF, pk, NULL, 0) != CRYPTO_PUBLICKEYBYTES)
return CR_AUTH_USER_CREDENTIALS;
return CR_ERROR; // bad password in the user table
info->password_used= PASSWORD_USED_YES;
/* prepare random nonce */
if (my_random_bytes((unsigned char *)nonce, (int)sizeof(nonce)))
return CR_AUTH_USER_CREDENTIALS;
return CR_ERROR; // eh? OpenSSL error
/* send it */
if (vio->write_packet(vio, reply + CRYPTO_BYTES, NONCE_BYTES))
@ -63,7 +63,7 @@ static int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
memcpy(reply, pkt, CRYPTO_BYTES);
if (crypto_sign_open(reply, CRYPTO_BYTES + NONCE_BYTES, pk))
return CR_ERROR;
return CR_AUTH_USER_CREDENTIALS; // wrong password provided by the user
return CR_OK;
}

View File

@ -875,7 +875,9 @@ get_openssl()
readonly OPENSSL_BINARY
}
#
# Generate a string equivalent to 16 random bytes
#
wsrep_gen_secret()
{
get_openssl
@ -889,16 +891,36 @@ wsrep_gen_secret()
fi
}
#
# Checking if the address passed to us is local.
# If the second parameter is nonzero, then this function
# does not check for matches with local domain names:
#
is_local_ip()
{
[ "$1" = '127.0.0.1' ] && return 0
[ "$1" = '127.0.0.2' ] && return 0
[ "$1" = 'localhost' ] && return 0
[ "$1" = '[::1]' ] && return 0
[ "$1" = "$(hostname -s)" ] && return 0
[ "$1" = "$(hostname -f)" ] && return 0
[ "$1" = "$(hostname -d)" ] && return 0
# Rapid recognition of the most common cases:
[ "$1" = '127.0.0.1' -o \
"$1" = '127.0.0.2' -o \
"$1" = 'localhost' -o \
"$1" = '[::1]' ] && return 0
# If the address starts with "127." this is probably a local
# address, but we need to clarify what follows this prefix:
if [ "${1#127.}" != "$1" ]; then
# All 127.0.0.0/8 addresses are local:
if echo "$1" | grep -q -E '^127\.[0-9]+\.[0-9]+\.[0-9]+$'; then
return 0
fi
fi
# If the second parameter is nonzero, then we will skip
# the domain name check:
if [ "${2:-0}" -eq 0 ]; then
# We consider all the names of a given host to be local addresses:
[ "$1" = "$(hostname -s)" -o \
"$1" = "$(hostname -f)" -o \
"$1" = "$(hostname -d)" ] && return 0
fi
# Now let's check if the given address is assigned to
# one of the network cards:
local ip_util="$(command -v ip)"
if [ -n "$ip_util" ]; then
# ip address show ouput format is " inet[6] <address>/<mask>":
@ -914,7 +936,6 @@ is_local_ip()
| grep -F " $1 " >/dev/null && return 0
fi
fi
return 1
}

View File

@ -6129,6 +6129,7 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
*/
set_max_sum_func_level(thd, select);
set_field(new_field);
depended_from= (*((Item_field**)res))->depended_from;
return 0;
}
else

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2002, 2016, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
Copyright (c) 2010, 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
@ -1779,7 +1779,6 @@ double Item_in_subselect::val_real()
As far as Item_in_subselect called only from Item_in_optimizer this
method should not be used
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
if (forced_const)
return value;
@ -2255,11 +2254,12 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
*/
Item *item= (Item*) select_lex->item_list.head();
if (select_lex->table_list.elements)
if (select_lex->table_list.elements ||
!(select_lex->master_unit()->is_unit_op()))
{
Item *having= item;
Item *orig_item= item;
item= func->create(thd, expr, item);
if (!abort_on_null && orig_item->maybe_null)
{
@ -2303,32 +2303,28 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
}
else
{
if (select_lex->master_unit()->is_unit_op())
{
LEX_CSTRING field_name= {STRING_WITH_LEN("<result>") };
Item *new_having=
func->create(thd, expr,
new (thd->mem_root) Item_ref_null_helper(thd,
DBUG_ASSERT(select_lex->master_unit()->is_unit_op());
LEX_CSTRING field_name= {STRING_WITH_LEN("<result>") };
Item *new_having=
func->create(thd, expr,
new (thd->mem_root) Item_ref_null_helper(thd,
&select_lex->context,
this,
&select_lex->ref_pointer_array[0],
(char *)"<no matter>",
&field_name));
if (!abort_on_null && left_expr->maybe_null)
{
disable_cond_guard_for_const_null_left_expr(0);
if (!(new_having= new (thd->mem_root) Item_func_trig_cond(thd, new_having,
if (!abort_on_null && left_expr->maybe_null)
{
disable_cond_guard_for_const_null_left_expr(0);
if (!(new_having= new (thd->mem_root) Item_func_trig_cond(thd, new_having,
get_cond_guard(0))))
DBUG_RETURN(true);
}
new_having->name= in_having_cond;
if (fix_having(new_having, select_lex))
DBUG_RETURN(true);
*having_item= new_having;
}
else
DBUG_ASSERT(false);
new_having->name= in_having_cond;
if (fix_having(new_having, select_lex))
DBUG_RETURN(true);
*having_item= new_having;
}
}

View File

@ -5407,7 +5407,7 @@ static int init_server_components()
}
}
if (opt_bin_log)
if (!opt_help && opt_bin_log)
{
if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname,
TRUE))

View File

@ -582,7 +582,7 @@ extern ulonglong my_pcre_frame_size;
*/
extern my_bool opt_large_pages;
extern uint opt_large_page_size;
extern char lc_messages_dir[FN_REFLEN];
extern MYSQL_PLUGIN_IMPORT char lc_messages_dir[FN_REFLEN];
extern char *lc_messages_dir_ptr, *log_error_file_ptr;
extern MYSQL_PLUGIN_IMPORT char reg_ext[FN_EXTLEN];
extern MYSQL_PLUGIN_IMPORT uint reg_ext_length;

View File

@ -3426,8 +3426,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
#endif
if (open_tables)
res= check_dependencies_in_with_clauses(m_lex->with_clauses_list) ||
instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
res= instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
if (likely(!res))
{

View File

@ -3520,7 +3520,11 @@ open_and_process_table(THD *thd, TABLE_LIST *tables, uint *counter, uint flags,
if (tables->derived)
{
if (!tables->view)
{
if (!tables->is_derived())
tables->set_derived();
goto end;
}
/*
We restore view's name and database wiped out by derived tables
processing and fall back to standard open process in order to
@ -3530,35 +3534,6 @@ open_and_process_table(THD *thd, TABLE_LIST *tables, uint *counter, uint flags,
tables->db= tables->view_db;
tables->table_name= tables->view_name;
}
else if (tables->select_lex)
{
/*
Check whether 'tables' refers to a table defined in a with clause.
If so set the reference to the definition in tables->with.
*/
if (!tables->with)
tables->with= tables->select_lex->find_table_def_in_with_clauses(tables);
/*
If 'tables' is defined in a with clause set the pointer to the
specification from its definition in tables->derived.
*/
if (tables->with)
{
if (tables->is_recursive_with_table() &&
!tables->is_with_table_recursive_reference())
{
tables->with->rec_outer_references++;
With_element *with_elem= tables->with;
while ((with_elem= with_elem->get_next_mutually_recursive()) !=
tables->with)
with_elem->rec_outer_references++;
}
if (tables->set_as_with_table(thd, tables->with))
DBUG_RETURN(1);
else
goto end;
}
}
if (!tables->derived && is_infoschema_db(&tables->db))
{

View File

@ -2736,6 +2736,60 @@ void THD::close_active_vio()
#endif
/*
@brief MySQL parser used for recursive invocations
@param old_lex The LEX structure in the state when this parser
is called recursively
@param lex The LEX structure used to parse a new SQL fragment
@param str The SQL fragment to parse
@param str_len The length of the SQL fragment to parse
@param stmt_prepare_mode true <=> when parsing a prepare statement
@details
This function is to be used when parsing of an SQL fragment is
needed within one of the grammar rules.
@notes
Currently the function is used only when the specification of a CTE
is parsed for the not first and not recursive references of the CTE.
@retval false On a successful parsing of the fragment
@retval true Otherwise
*/
bool THD::sql_parser(LEX *old_lex, LEX *lex,
char *str, uint str_len, bool stmt_prepare_mode)
{
extern int MYSQLparse(THD * thd);
bool parse_status= false;
Parser_state parser_state;
Parser_state *old_parser_state= m_parser_state;
if (parser_state.init(this, str, str_len))
return true;
m_parser_state= &parser_state;
parser_state.m_lip.stmt_prepare_mode= stmt_prepare_mode;
parser_state.m_lip.multi_statements= false;
parser_state.m_lip.m_digest= NULL;
lex->param_list= old_lex->param_list;
lex->sphead= old_lex->sphead;
lex->spname= old_lex->spname;
lex->spcont= old_lex->spcont;
lex->sp_chistics= old_lex->sp_chistics;
lex->trg_chistics= old_lex->trg_chistics;
parse_status= MYSQLparse(this) != 0;
m_parser_state= old_parser_state;
return parse_status;
}
struct Item_change_record: public ilink
{
Item **place;

View File

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2009, 2020, MariaDB Corporation.
Copyright (c) 2009, 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
@ -958,7 +958,7 @@ mysqld_collation_get_by_name(const char *name,
static inline bool is_supported_parser_charset(CHARSET_INFO *cs)
{
return MY_TEST(cs->mbminlen == 1);
return MY_TEST(cs->mbminlen == 1 && cs->number != 17 /* filename */);
}
#ifdef MYSQL_SERVER
@ -4226,15 +4226,11 @@ public:
to resolve all CTE names as we don't need this message to be thrown
for any CTE references.
*/
if (!lex->with_clauses_list)
if (!lex->with_cte_resolution)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
return TRUE;
}
/* This will allow to throw an error later for non-CTE references */
to->str= NULL;
to->length= 0;
return FALSE;
}
to->str= strmake(db.str, db.length);
@ -4839,6 +4835,9 @@ public:
mysql_mutex_unlock(&LOCK_thread_count);
}
bool sql_parser(LEX *old_lex, LEX *lex,
char *str, uint str_len, bool stmt_prepare_mode);
uint get_net_wait_timeout()
{

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2016, 2017 MariaDB
Copyright (c) 2016, 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
@ -75,7 +75,7 @@ bool With_clause::add_with_element(With_element *elem)
true on failure
*/
bool check_dependencies_in_with_clauses(With_clause *with_clauses_list)
bool LEX::check_dependencies_in_with_clauses()
{
for (With_clause *with_clause= with_clauses_list;
with_clause;
@ -91,6 +91,200 @@ bool check_dependencies_in_with_clauses(With_clause *with_clauses_list)
}
/**
@brief
Resolve references to CTE in specification of hanging CTE
@details
A CTE to which there are no references in the query is called hanging CTE.
Although such CTE is not used for execution its specification must be
subject to context analysis. All errors concerning references to
non-existing tables or fields occurred in the specification must be
reported as well as all other errors caught at the prepare stage.
The specification of a hanging CTE might contain references to other
CTE outside of the specification and within it if the specification
contains a with clause. This function resolves all such references for
all hanging CTEs encountered in the processed query.
@retval
false on success
true on failure
*/
bool
LEX::resolve_references_to_cte_in_hanging_cte()
{
for (With_clause *with_clause= with_clauses_list;
with_clause; with_clause= with_clause->next_with_clause)
{
for (With_element *with_elem= with_clause->with_list.first;
with_elem; with_elem= with_elem->next)
{
if (!with_elem->is_referenced())
{
TABLE_LIST *first_tbl=
with_elem->spec->first_select()->table_list.first;
TABLE_LIST **with_elem_end_pos= with_elem->head->tables_pos.end_pos;
if (first_tbl && resolve_references_to_cte(first_tbl, with_elem_end_pos))
return true;
}
}
}
return false;
}
/**
@brief
Resolve table references to CTE from a sub-chain of table references
@param tables Points to the beginning of the sub-chain
@param tables_last Points to the address with the sub-chain barrier
@details
The method resolves tables references to CTE from the chain of
table references specified by the parameters 'tables' and 'tables_last'.
It resolves the references against the CTE definition occurred in a query
or the specification of a CTE whose parsing tree is represented by
this LEX structure. The method is always called right after the process
of parsing the query or of the specification of a CTE has been finished,
thus the chain of table references used in the parsed fragment has been
already built. It is assumed that parameters of the method specify a
a sub-chain of this chain.
If a table reference can be potentially a table reference to a CTE and it
has not been resolved yet then the method tries to find the definition
of the CTE against which the reference can be resolved. If it succeeds
it sets the field TABLE_LIST::with to point to the found definition.
It also sets the field TABLE_LIST::derived to point to the specification
of the found CTE and sets TABLE::db.str to empty_c_string. This will
allow to handle this table reference like a reference to a derived handle.
If another table reference has been already resolved against this CTE
and this CTE is not recursive then a clone of the CTE specification is
constructed using the function With_element::clone_parsed_spec() and
TABLE_LIST::derived is set to point to this clone rather than to the
original specification.
If the method does not find a matched CTE definition in the parsed fragment
then in the case when the flag this->only_cte_resolution is set to true
it just moves to the resolution of the next table reference from the
specified sub-chain while in the case when this->only_cte_resolution is set
to false the method additionally sets an mdl request for this table
reference.
@notes
The flag this->only_cte_resolution is set to true in the cases when
the failure to resolve a table reference as a CTE reference within
the fragment associated with this LEX structure does not imply that
this table reference cannot be resolved as such at all.
@retval false On success: no errors reported, no memory allocations failed
@retval true Otherwise
*/
bool LEX::resolve_references_to_cte(TABLE_LIST *tables,
TABLE_LIST **tables_last)
{
With_element *with_elem= 0;
for (TABLE_LIST *tbl= tables; tbl != *tables_last; tbl= tbl->next_global)
{
if (tbl->derived)
continue;
if (!tbl->db.length && !tbl->with)
tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl);
if (!tbl->with) // no CTE matches table reference tbl
{
if (only_cte_resolution)
continue;
if (!tbl->db.length) // no database specified in table reference tbl
{
if (!thd->db.length) // no default database is set
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
return true;
}
if (copy_db_to(&tbl->db))
return true;
if (!(tbl->table_options & TL_OPTION_ALIAS))
tbl->mdl_request.init(MDL_key::TABLE, tbl->db.str,
tbl->table_name.str,
tbl->mdl_type, MDL_TRANSACTION);
tbl->mdl_request.set_type((tbl->lock_type >= TL_WRITE_ALLOW_WRITE) ?
MDL_SHARED_WRITE : MDL_SHARED_READ);
}
continue;
}
with_elem= tbl->with;
if (tbl->is_recursive_with_table() &&
!tbl->is_with_table_recursive_reference())
{
tbl->with->rec_outer_references++;
while ((with_elem= with_elem->get_next_mutually_recursive()) !=
tbl->with)
with_elem->rec_outer_references++;
}
if (!with_elem->is_used_in_query || with_elem->is_recursive)
{
tbl->derived= with_elem->spec;
if (tbl->derived != tbl->select_lex->master_unit() &&
!with_elem->is_recursive &&
!tbl->is_with_table_recursive_reference())
{
tbl->derived->move_as_slave(tbl->select_lex);
}
with_elem->is_used_in_query= true;
}
else
{
if (!(tbl->derived= tbl->with->clone_parsed_spec(thd->lex, tbl)))
return true;
}
tbl->db.str= empty_c_string;
tbl->db.length= 0;
tbl->schema_table= 0;
if (tbl->derived)
{
tbl->derived->first_select()->linkage= DERIVED_TABLE_TYPE;
}
if (tbl->with->is_recursive && tbl->is_with_table_recursive_reference())
continue;
with_elem->inc_references();
}
return false;
}
/**
@brief
Find out dependencies between CTEs, resolve references to them
@details
The function can be called in two modes. With this->with_cte_resolution
set to false the function only finds out all dependencies between CTEs
used in a query expression with a WITH clause whose parsing has been
just finished. Based on these dependencies recursive CTEs are detected.
If this->with_cte_resolution is set to true the function additionally
resolves all references to CTE occurred in this query expression.
@retval
true on failure
false on success
*/
bool
LEX::check_cte_dependencies_and_resolve_references()
{
if (check_dependencies_in_with_clauses())
return true;
if (!with_cte_resolution)
return false;
if (resolve_references_to_cte(query_tables, query_tables_last))
return true;
if (resolve_references_to_cte_in_hanging_cte())
return true;
return false;
}
/**
@brief
Check dependencies between tables defined in this with clause
@ -129,10 +323,11 @@ bool With_clause::check_dependencies()
elem != with_elem;
elem= elem->next)
{
if (lex_string_cmp(system_charset_info, with_elem->query_name,
elem->query_name) == 0)
if (my_strcasecmp(system_charset_info, with_elem->get_name_str(),
elem->get_name_str()) == 0)
{
my_error(ER_DUP_QUERY_NAME, MYF(0), with_elem->query_name->str);
my_error(ER_DUP_QUERY_NAME, MYF(0),
with_elem->get_name_str());
return true;
}
}
@ -239,13 +434,12 @@ With_element *With_clause::find_table_def(TABLE_LIST *table,
with_elem != barrier;
with_elem= with_elem->next)
{
if (my_strcasecmp(system_charset_info, with_elem->query_name->str,
if (my_strcasecmp(system_charset_info, with_elem->get_name_str(),
table->table_name.str) == 0 &&
!table->is_fqtn)
{
table->set_derived();
table->db.str= empty_c_string;
table->db.length= 0;
with_elem->referenced= true;
return with_elem;
}
}
@ -602,7 +796,7 @@ bool With_clause::check_anchors()
if (elem == with_elem)
{
my_error(ER_RECURSIVE_WITHOUT_ANCHORS, MYF(0),
with_elem->query_name->str);
with_elem->get_name_str());
return true;
}
}
@ -635,7 +829,7 @@ bool With_clause::check_anchors()
if (elem->work_dep_map & elem->get_elem_map())
{
my_error(ER_UNACCEPTABLE_MUTUAL_RECURSION, MYF(0),
with_elem->query_name->str);
with_elem->get_name_str());
return true;
}
}
@ -787,7 +981,8 @@ bool With_element::set_unparsed_spec(THD *thd, char *spec_start, char *spec_end,
@brief
Create a clone of the specification for the given with table
@param thd The context of the statement containing this with element
@param old_lex The LEX structure created for the query or CTE specification
where this With_element is defined
@param with_table The reference to the table defined in this element for which
the clone is created.
@ -797,12 +992,13 @@ bool With_element::set_unparsed_spec(THD *thd, char *spec_start, char *spec_end,
this element.
The clone is created when the string with the specification saved in
unparsed_spec is fed into the parser as an input string. The parsing
this string a unit object representing the specification is build.
this string a unit object representing the specification is built.
A chain of all table references occurred in the specification is also
formed.
The method includes the new unit and its sub-unit into hierarchy of
the units of the main query. I also insert the constructed chain of the
table references into the chain of all table references of the main query.
The method resolves all references to CTE in the clone.
@note
Clones is created only for not first references to tables defined in
@ -818,115 +1014,129 @@ bool With_element::set_unparsed_spec(THD *thd, char *spec_start, char *spec_end,
NULL - otherwise
*/
st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
st_select_lex_unit *With_element::clone_parsed_spec(LEX *old_lex,
TABLE_LIST *with_table)
{
THD *thd= old_lex->thd;
LEX *lex;
st_select_lex_unit *res= NULL;
Query_arena backup;
Query_arena *arena= thd->activate_stmt_arena_if_needed(&backup);
st_select_lex_unit *res= NULL;
if (!(lex= (LEX*) new(thd->mem_root) st_lex_local))
{
if (arena)
thd->restore_active_arena(arena, &backup);
return res;
}
LEX *old_lex= thd->lex;
thd->lex= lex;
bool parse_status= false;
Parser_state parser_state;
TABLE_LIST *spec_tables;
TABLE_LIST *spec_tables_tail;
st_select_lex *with_select;
char save_end= unparsed_spec.str[unparsed_spec.length];
((char*) &unparsed_spec.str[unparsed_spec.length])[0]= '\0';
if (parser_state.init(thd, (char*) unparsed_spec.str, (unsigned int)unparsed_spec.length))
goto err;
parser_state.m_lip.stmt_prepare_mode= stmt_prepare_mode;
parser_state.m_lip.multi_statements= false;
parser_state.m_lip.m_digest= NULL;
const_cast<char*>(unparsed_spec.str)[unparsed_spec.length]= '\0';
lex_start(thd);
lex->clone_spec_offset= unparsed_spec_offset;
lex->param_list= old_lex->param_list;
lex->sphead= old_lex->sphead;
lex->spname= old_lex->spname;
lex->spcont= old_lex->spcont;
lex->sp_chistics= old_lex->sp_chistics;
lex->with_cte_resolution= true;
lex->stmt_lex= old_lex;
with_select= &lex->select_lex;
with_select->select_number= ++thd->lex->stmt_lex->current_select_number;
parse_status= parse_sql(thd, &parser_state, 0);
((char*) &unparsed_spec.str[unparsed_spec.length])[0]= save_end;
/*
The specification of a CTE is to be parsed as a regular query.
At the very end of the parsing query the function
check_cte_dependencies_and_resolve_references() will be called.
It will check the dependencies between CTEs that are defined
within the query and will resolve CTE references in this query.
If a table reference is not resolved as a CTE reference within
this query it still can be resolved as a reference to a CTE defined
in the same clause as the CTE whose specification is to be parsed
or defined in an embedding CTE definition.
Example:
with
cte1 as ( ... ),
cte2 as ([WITH ...] select ... from cte1 ...)
select ... from cte2 as r, ..., cte2 as s ...
Here the specification of cte2 has be cloned for table reference
with alias s1. The specification contains a reference to cte1
that is defined outside this specification. If the reference to
cte1 cannot be resolved within the specification of cte2 it's
not necessarily has to be a reference to a non-CTE table. That's
why the flag lex->only_cte_resolution has to be set to true
before parsing of the specification of cte2 invoked by this
function starts. Otherwise an mdl_lock would be requested for s
and this would not be correct.
*/
lex->only_cte_resolution= true;
lex->stmt_lex= old_lex->stmt_lex ? old_lex->stmt_lex : old_lex;
parse_status= thd->sql_parser(old_lex, lex,
(char*) unparsed_spec.str,
(unsigned int)unparsed_spec.length,
stmt_prepare_mode);
const_cast<char*>(unparsed_spec.str)[unparsed_spec.length]= save_end;
with_select= lex->unit.first_select();
with_select->select_number= ++lex->stmt_lex->current_select_number;
if (parse_status)
goto err;
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
goto err;
spec_tables= lex->query_tables;
spec_tables_tail= 0;
for (TABLE_LIST *tbl= spec_tables;
tbl;
tbl= tbl->next_global)
/*
The global chain of TABLE_LIST objects created for the specification that
just has been parsed is added to such chain that contains the reference
to the CTE whose specification is parsed right after the TABLE_LIST object
created for the reference.
*/
if (lex->query_tables)
{
if (!tbl->derived && !tbl->schema_table &&
thd->open_temporary_table(tbl))
goto err;
spec_tables_tail= tbl;
}
if (spec_tables)
{
if (with_table->next_global)
head->tables_pos.set_start_pos(&with_table->next_global);
head->tables_pos.set_end_pos(lex->query_tables_last);
TABLE_LIST *next_tbl= with_table->next_global;
if (next_tbl)
{
spec_tables_tail->next_global= with_table->next_global;
with_table->next_global->prev_global= &spec_tables_tail->next_global;
*(lex->query_tables->prev_global= next_tbl->prev_global)=
lex->query_tables;
*(next_tbl->prev_global= lex->query_tables_last)= next_tbl;
}
else
{
old_lex->query_tables_last= &spec_tables_tail->next_global;
*(lex->query_tables->prev_global= old_lex->query_tables_last)=
lex->query_tables;
old_lex->query_tables_last= lex->query_tables_last;
}
spec_tables->prev_global= &with_table->next_global;
with_table->next_global= spec_tables;
}
res= &lex->unit;
res->with_element= this;
/*
The unit of the specification that just has been parsed is included
as a slave of the select that contained in its from list the table
reference for which the unit has been created.
*/
lex->unit.include_down(with_table->select_lex);
lex->unit.set_slave(with_select);
lex->unit.set_slave(with_select);
lex->unit.cloned_from= spec;
old_lex->all_selects_list=
(st_select_lex*) (lex->all_selects_list->
insert_chain_before(
(st_select_lex_node **) &(old_lex->all_selects_list),
with_select));
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
res= NULL;
/*
Resolve references to CTE from the spec_tables list that has not
been resolved yet.
*/
for (TABLE_LIST *tbl= spec_tables;
tbl;
tbl= tbl->next_global)
{
if (!tbl->with)
tbl->with= with_select->find_table_def_in_with_clauses(tbl);
if (tbl == spec_tables_tail)
break;
}
if (check_table_access(thd, SELECT_ACL, spec_tables, FALSE, UINT_MAX, FALSE))
goto err;
lex->sphead= NULL; // in order not to delete lex->sphead
/*
Now all references to the CTE defined outside of the cloned specification
has to be resolved. Additionally if old_lex->only_cte_resolution == false
for the table references that has not been resolved requests for mdl_locks
has to be set.
*/
lex->only_cte_resolution= old_lex->only_cte_resolution;
if (lex->resolve_references_to_cte(lex->query_tables,
lex->query_tables_last))
{
res= NULL;
goto err;
}
lex->sphead= NULL; // in order not to delete lex->sphead
lex_end(lex);
err:
if (arena)
thd->restore_active_arena(arena, &backup);
thd->lex= old_lex;
return res;
}
@ -1096,58 +1306,6 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table)
}
/**
@brief
Set the specifying unit in this reference to a with table
@details
The method assumes that the given element with_elem defines the table T
this table reference refers to.
If this is the first reference to T the method just sets its specification
in the field 'derived' as the unit that yields T. Otherwise the method
first creates a clone specification and sets rather this clone in this field.
@retval
false on success
true on failure
*/
bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem)
{
if (table)
{
/*
This table was prematurely identified as a temporary table.
We correct it here, but it's not a nice solution in the case
when the temporary table with this name is not used anywhere
else in the query.
*/
thd->mark_tmp_table_as_free_for_reuse(table);
table= 0;
}
with= with_elem;
schema_table= NULL;
if (!with_elem->is_referenced() || with_elem->is_recursive)
{
derived= with_elem->spec;
if (derived != select_lex->master_unit() &&
!with_elem->is_recursive &&
!is_with_table_recursive_reference())
{
derived->move_as_slave(select_lex);
}
}
else
{
if(!(derived= with_elem->clone_parsed_spec(thd, this)))
return true;
}
derived->first_select()->linkage= DERIVED_TABLE_TYPE;
with_elem->inc_references();
return false;
}
bool TABLE_LIST::is_recursive_with_table()
{
return with && with->is_recursive;
@ -1247,7 +1405,7 @@ bool st_select_lex::check_unrestricted_recursive(bool only_standard_compliant)
if (only_standard_compliant && with_elem->is_unrestricted())
{
my_error(ER_NOT_STANDARD_COMPLIANT_RECURSIVE,
MYF(0), with_elem->query_name->str);
MYF(0), with_elem->get_name_str());
return true;
}
@ -1447,7 +1605,7 @@ void With_clause::print(String *str, enum_query_type query_type)
void With_element::print(String *str, enum_query_type query_type)
{
str->append(query_name);
str->append(get_name());
if (column_list.elements)
{
List_iterator_fast<LEX_CSTRING> li(column_list);

View File

@ -24,6 +24,39 @@ class select_unit;
struct st_unit_ctxt_elem;
/**
@class With_element_head
@brief Head of the definition of a CTE table
It contains the name of the CTE and it contains the position of the subchain
of table references used in the definition in the global chain of table
references used in the query where this definition is encountered.
*/
class With_element_head : public Sql_alloc
{
/* The name of the defined CTE */
LEX_CSTRING *query_name;
public:
/*
The structure describing the subchain of the table references used in
the specification of the defined CTE in the global chain of table
references used in the query. The structure is fully defined only
after the CTE definition has been parsed.
*/
TABLE_CHAIN tables_pos;
With_element_head(LEX_CSTRING *name)
: query_name(name)
{
tables_pos.set_start_pos(0);
tables_pos.set_end_pos(0);
}
friend class With_element;
};
/**
@class With_element
@brief Definition of a CTE table
@ -85,9 +118,22 @@ private:
subqueries and specifications of other with elements).
*/
uint references;
/*
true <=> this With_element is referred in the query in which the
element is defined
*/
bool referenced;
/*
true <=> this With_element is needed for the execution of the query
in which the element is defined
*/
bool is_used_in_query;
/*
Unparsed specification of the query that specifies this element.
It used to build clones of the specification if they are needed.
It's used to build clones of the specification if they are needed.
*/
LEX_CSTRING unparsed_spec;
/* Offset of the specification in the input string */
@ -101,10 +147,11 @@ private:
public:
/*
The name of the table introduced by this with elememt. The name
can be used in FROM lists of the queries in the scope of the element.
Contains the name of the defined With element and the position of
the subchain of the tables references used by its definition in the
global chain of TABLE_LIST objects created for the whole query.
*/
LEX_CSTRING *query_name;
With_element_head *head;
/*
Optional list of column names to name the columns of the table introduced
by this with element. It is used in the case when the names are not
@ -162,18 +209,27 @@ public:
/* List of derived tables containing recursive references to this CTE */
SQL_I_List<TABLE_LIST> derived_with_rec_ref;
With_element(LEX_CSTRING *name,
With_element(With_element_head *h,
List <LEX_CSTRING> list,
st_select_lex_unit *unit)
: next(NULL), base_dep_map(0), derived_dep_map(0),
sq_dep_map(0), work_dep_map(0), mutually_recursive(0),
top_level_dep_map(0), sq_rec_ref(NULL),
next_mutually_recursive(NULL), references(0),
query_name(name), column_list(list), spec(unit),
referenced(false), is_used_in_query(false),
head(h), column_list(list), spec(unit),
is_recursive(false), rec_outer_references(0), with_anchor(false),
level(0), rec_result(NULL)
{ unit->with_element= this; }
LEX_CSTRING *get_name() { return head->query_name; }
const char *get_name_str() { return get_name()->str; }
void set_tables_start_pos(TABLE_LIST **pos)
{ head->tables_pos.set_start_pos(pos); }
void set_tables_end_pos(TABLE_LIST **pos)
{ head->tables_pos.set_end_pos(pos); }
bool check_dependencies_in_spec();
void check_dependencies_in_select(st_select_lex *sl, st_unit_ctxt_elem *ctxt,
@ -200,9 +256,9 @@ public:
bool set_unparsed_spec(THD *thd, char *spec_start, char *spec_end,
my_ptrdiff_t spec_offset);
st_select_lex_unit *clone_parsed_spec(THD *thd, TABLE_LIST *with_table);
st_select_lex_unit *clone_parsed_spec(LEX *old_lex, TABLE_LIST *with_table);
bool is_referenced() { return references != 0; }
bool is_referenced() { return referenced; }
void inc_references() { references++; }
@ -260,6 +316,12 @@ public:
void prepare_for_next_iteration();
friend class With_clause;
friend
bool LEX::resolve_references_to_cte(TABLE_LIST *tables,
TABLE_LIST **tables_last);
friend
bool LEX::resolve_references_to_cte_in_hanging_cte();
};
const uint max_number_of_elements_in_with_clause= sizeof(table_map)*8;
@ -356,8 +418,10 @@ public:
friend class With_element;
friend
bool
check_dependencies_in_with_clauses(With_clause *with_clauses_list);
bool LEX::check_dependencies_in_with_clauses();
friend
bool LEX::resolve_references_to_cte_in_hanging_cte();
};
inline

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates.
Copyright (c) 2009, 2020, MariaDB Corporation
Copyright (c) 2009, 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
@ -702,6 +702,8 @@ void LEX::start(THD *thd_arg)
explain_json= false;
context_analysis_only= 0;
derived_tables= 0;
with_cte_resolution= false;
only_cte_resolution= false;
safe_to_cache_query= 1;
parsing_options.reset();
empty_field_list_on_rset= 0;
@ -2300,6 +2302,7 @@ void st_select_lex_unit::init_query()
is_view= false;
with_clause= 0;
with_element= 0;
cloned_from= 0;
columns_are_renamed= false;
intersect_mark= NULL;
with_wrapped_tvc= false;

View File

@ -846,6 +846,8 @@ public:
With_clause *with_clause;
/* With element where this unit is used as the specification (if any) */
With_element *with_element;
/* The unit used as a CTE specification from which this unit is cloned */
st_select_lex_unit *cloned_from;
/* thread handler */
THD *thd;
/*
@ -1378,7 +1380,9 @@ public:
}
With_element *get_with_element()
{
return master_unit()->with_element;
return master_unit()->cloned_from ?
master_unit()->cloned_from->with_element :
master_unit()->with_element;
}
With_element *find_table_def_in_with_clauses(TABLE_LIST *table);
bool check_unrestricted_recursive(bool only_standard_compliant);
@ -3062,6 +3066,20 @@ public:
*/
uint8 derived_tables;
uint8 context_analysis_only;
/*
true <=> The parsed fragment requires resolution of references to CTE
at the end of parsing. This name resolution process involves searching
for possible dependencies between CTE defined in the parsed fragment and
detecting possible recursive references.
The flag is set to true if the fragment contains CTE definitions.
*/
bool with_cte_resolution;
/*
true <=> only resolution of references to CTE are required in the parsed
fragment, no checking of dependencies between CTE is required.
This flag is used only when parsing clones of CTE specifications.
*/
bool only_cte_resolution;
bool local_file;
bool check_exists;
bool autocommit;
@ -4030,6 +4048,12 @@ public:
return !create_like() && !create_select();
}
bool check_dependencies_in_with_clauses();
bool resolve_references_to_cte_in_hanging_cte();
bool check_cte_dependencies_and_resolve_references();
bool resolve_references_to_cte(TABLE_LIST *tables,
TABLE_LIST **tables_last);
SELECT_LEX *exclude_last_select();
bool add_unit_in_brackets(SELECT_LEX *nselect);
void check_automatic_up(enum sub_select_type type);

View File

@ -3506,9 +3506,6 @@ mysql_execute_command(THD *thd)
thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
}
if (check_dependencies_in_with_clauses(thd->lex->with_clauses_list))
DBUG_RETURN(1);
#ifdef HAVE_REPLICATION
if (unlikely(thd->slave_thread))
{
@ -8060,7 +8057,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->is_fqtn= TRUE;
ptr->db= table->db;
}
else if (lex->copy_db_to(&ptr->db))
else if (!lex->with_cte_resolution && lex->copy_db_to(&ptr->db))
DBUG_RETURN(0);
else
ptr->is_fqtn= FALSE;
@ -8075,9 +8072,11 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
if (ptr->db.length && ptr->db.str != any_db)
ptr->db.length= my_casedn_str(files_charset_info, (char*) ptr->db.str);
}
ptr->table_name= table->table;
ptr->lock_type= lock_type;
ptr->mdl_type= mdl_type;
ptr->table_options= table_options;
ptr->updating= MY_TEST(table_options & TL_OPTION_UPDATING);
/* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */
ptr->force_index= MY_TEST(table_options & TL_OPTION_FORCE_INDEX);
@ -8765,8 +8764,10 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type, bool for_update
{
tables->lock_type= lock_type;
tables->updating= for_update;
tables->mdl_request.set_type((lock_type >= TL_WRITE_ALLOW_WRITE) ?
MDL_SHARED_WRITE : MDL_SHARED_READ);
if (tables->db.length)
tables->mdl_request.set_type((lock_type >= TL_WRITE_ALLOW_WRITE) ?
MDL_SHARED_WRITE : MDL_SHARED_READ);
}
DBUG_VOID_RETURN;
}

View File

@ -2359,9 +2359,6 @@ static bool check_prepared_statement(Prepared_statement *stmt)
if (tables)
thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
if (check_dependencies_in_with_clauses(thd->lex->with_clauses_list))
goto error;
if (sql_command_flags[sql_command] & CF_HA_CLOSE)
mysql_ha_rm_tables(thd, tables);

View File

@ -431,12 +431,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
lex->link_first_table_back(view, link_to_local);
view->open_type= OT_BASE_ONLY;
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
{
res= TRUE;
goto err;
}
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/*
@ -889,6 +883,13 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
{
LEX *lex= thd->lex;
/*
Ensure character set number != 17 (character set = filename) and mbminlen=1
because these character sets are not parser friendly, which can give weird
sequence in .frm file of view and later give parsing error.
*/
DBUG_ASSERT(thd->charset()->mbminlen == 1 && thd->charset()->number != 17);
/*
View definition query -- a SELECT statement that fully defines view. It
is generated from the Item-tree built from the original (specified by
@ -1411,9 +1412,6 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
TABLE_LIST *tbl;
Security_context *security_ctx= 0;
if (check_dependencies_in_with_clauses(thd->lex->with_clauses_list))
goto err;
/*
Check rights to run commands (ANALYZE SELECT, EXPLAIN SELECT &
SHOW CREATE) which show underlying tables.

View File

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2010, 2020, MariaDB
Copyright (c) 2010, 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
@ -839,6 +839,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
class sp_head *sphead;
class sp_name *spname;
class sp_variable *spvar;
class With_element_head *with_element_head;
class With_clause *with_clause;
class Virtual_column_info *virtual_column;
@ -2207,7 +2208,7 @@ END_OF_INPUT
%type <with_clause> opt_with_clause with_clause
%type <lex_str_ptr> query_name
%type <with_element_head> with_element_head
%type <lex_str_list> opt_with_column_list
@ -3345,7 +3346,11 @@ call:
if (unlikely(Lex->call_statement_start(thd, $2)))
MYSQL_YYABORT;
}
opt_sp_cparam_list {}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
/* CALL parameters */
@ -4227,6 +4232,8 @@ sp_proc_stmt_return:
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
$3, lex)) ||
unlikely(sp->restore_lex(thd)))
@ -4236,6 +4243,8 @@ sp_proc_stmt_return:
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
if (unlikely(sp->m_handler->add_instr_preturn(thd, sp,
lex->spcont)))
MYSQL_YYABORT;
@ -5343,12 +5352,16 @@ create_select_query_expression:
{
Select->set_braces(0);
Select->set_with_clause($1);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
union_clause
| opt_with_clause SELECT_SYM create_select_part2
create_select_part3_union_not_ready create_select_part4
{
Select->set_with_clause($1);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| '(' create_select_query_specification ')'
| '(' create_select_query_specification ')'
@ -6097,6 +6110,8 @@ create_select_query_specification:
create_select_part4
{
Select->set_with_clause($1);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
@ -9205,6 +9220,8 @@ select:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT;
lex->current_select->set_with_clause($1);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
@ -13234,6 +13251,8 @@ do:
expr_list
{
Lex->insert_list= $3;
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
@ -13462,6 +13481,8 @@ insert:
}
insert_field_spec opt_insert_update
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
Lex->mark_first_table_as_inserting();
}
;
@ -13481,6 +13502,8 @@ replace:
}
insert_field_spec
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
Lex->mark_first_table_as_inserting();
}
;
@ -13729,7 +13752,11 @@ update:
*/
slex->set_lock_for_tables($3, slex->table_list.elements == 1);
}
opt_where_clause opt_order_clause delete_limit_clause {}
opt_where_clause opt_order_clause delete_limit_clause
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
update_list:
@ -13844,6 +13871,8 @@ single_multi:
{
if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex)))
MYSQL_YYABORT;
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
@ -14870,6 +14899,8 @@ load:
opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
opt_load_data_set_spec
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
Lex->mark_first_table_as_inserting();
}
;
@ -15287,6 +15318,8 @@ with_clause:
if (unlikely(with_clause == NULL))
MYSQL_YYABORT;
Lex->derived_tables|= DERIVED_WITH;
Lex->with_cte_resolution= true;
Lex->with_cte_resolution= true;
Lex->curr_with_clause= with_clause;
with_clause->add_to_list(Lex->with_clauses_list_last_next);
}
@ -15311,7 +15344,7 @@ with_list:
with_list_element:
query_name
with_element_head
opt_with_column_list
{
$2= new List<LEX_CSTRING> (Lex->with_column_list);
@ -15332,6 +15365,7 @@ with_list_element:
if (elem->set_unparsed_spec(thd, spec_start, $8,
spec_start - query_start))
MYSQL_YYABORT;
elem->set_tables_end_pos(lex->query_tables_last);
}
;
@ -15358,12 +15392,17 @@ with_column_list:
;
query_name:
with_element_head:
ident
{
$$= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
LEX_CSTRING *name=
(LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
if (unlikely($$ == NULL))
MYSQL_YYABORT;
$$= new (thd->mem_root) With_element_head(name);
if ($$ == NULL)
MYSQL_YYABORT;
$$->tables_pos.set_start_pos(Lex->query_tables_last);
}
;
@ -16308,7 +16347,10 @@ set:
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
start_option_value_list
{}
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| SET STATEMENT_SYM
{
Lex->set_stmt_init();
@ -17825,6 +17867,9 @@ view_select:
lex->create_view->check= $4;
lex->parsing_options.allows_variable= TRUE;
lex->current_select->set_with_clause($2);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;

View File

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2010, 2020, MariaDB
Copyright (c) 2010, 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
@ -232,6 +232,7 @@ void ORAerror(THD *thd, const char *s)
class sp_head *sphead;
class sp_name *spname;
class sp_variable *spvar;
class With_element_head *with_element_head;
class With_clause *with_clause;
class Virtual_column_info *virtual_column;
@ -1628,7 +1629,7 @@ END_OF_INPUT
%type <with_clause> opt_with_clause with_clause
%type <lex_str_ptr> query_name
%type <with_element_head> with_element_head
%type <lex_str_list> opt_with_column_list
@ -2999,7 +3000,11 @@ call:
if (unlikely(Lex->call_statement_start(thd, $2)))
MYSQL_YYABORT;
}
opt_sp_cparam_list {}
opt_sp_cparam_list
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
/* CALL parameters */
@ -3986,6 +3991,8 @@ sp_proc_stmt_return:
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
$3, lex)) ||
unlikely(sp->restore_lex(thd)))
@ -3995,6 +4002,8 @@ sp_proc_stmt_return:
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
if (unlikely(sp->m_handler->add_instr_preturn(thd, sp,
lex->spcont)))
MYSQL_YYABORT;
@ -5185,12 +5194,16 @@ create_select_query_expression:
{
Select->set_braces(0);
Select->set_with_clause($1);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
union_clause
| opt_with_clause SELECT_SYM create_select_part2
create_select_part3_union_not_ready create_select_part4
{
Select->set_with_clause($1);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| '(' create_select_query_specification ')'
| '(' create_select_query_specification ')'
@ -5939,6 +5952,8 @@ create_select_query_specification:
create_select_part4
{
Select->set_with_clause($1);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
@ -9135,6 +9150,8 @@ select:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT;
lex->current_select->set_with_clause($1);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
@ -13172,6 +13189,8 @@ do:
expr_list
{
Lex->insert_list= $3;
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
@ -13416,6 +13435,8 @@ insert:
}
insert_field_spec opt_insert_update
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
Lex->mark_first_table_as_inserting();
}
;
@ -13435,6 +13456,8 @@ replace:
}
insert_field_spec
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
Lex->mark_first_table_as_inserting();
}
;
@ -13683,7 +13706,11 @@ update:
*/
slex->set_lock_for_tables($3, slex->table_list.elements == 1);
}
opt_where_clause opt_order_clause delete_limit_clause {}
opt_where_clause opt_order_clause delete_limit_clause
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
update_list:
@ -13798,6 +13825,8 @@ single_multi:
{
if (unlikely(multi_delete_set_locks_and_link_aux_tables(Lex)))
MYSQL_YYABORT;
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;
@ -14830,6 +14859,8 @@ load:
opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
opt_load_data_set_spec
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
Lex->mark_first_table_as_inserting();
}
;
@ -15247,6 +15278,8 @@ with_clause:
if (unlikely(with_clause == NULL))
MYSQL_YYABORT;
Lex->derived_tables|= DERIVED_WITH;
Lex->with_cte_resolution= true;
Lex->with_cte_resolution= true;
Lex->curr_with_clause= with_clause;
with_clause->add_to_list(Lex->with_clauses_list_last_next);
}
@ -15271,7 +15304,7 @@ with_list:
with_list_element:
query_name
with_element_head
opt_with_column_list
{
$2= new List<LEX_CSTRING> (Lex->with_column_list);
@ -15292,6 +15325,7 @@ with_list_element:
if (elem->set_unparsed_spec(thd, spec_start, $8,
spec_start - query_start))
MYSQL_YYABORT;
elem->set_tables_end_pos(lex->query_tables_last);
}
;
@ -15318,12 +15352,17 @@ with_column_list:
;
query_name:
with_element_head:
ident
{
$$= (LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
LEX_CSTRING *name=
(LEX_CSTRING *) thd->memdup(&$1, sizeof(LEX_CSTRING));
if (unlikely($$ == NULL))
MYSQL_YYABORT;
$$= new (thd->mem_root) With_element_head(name);
if ($$ == NULL)
MYSQL_YYABORT;
$$->tables_pos.set_start_pos(Lex->query_tables_last);
}
;
@ -16305,7 +16344,10 @@ set:
sp_create_assignment_lex(thd, yychar == YYEMPTY);
}
start_option_value_list
{}
{
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
| SET STATEMENT_SYM
{
Lex->set_stmt_init();
@ -17873,6 +17915,9 @@ view_select:
lex->create_view->check= $4;
lex->parsing_options.allows_variable= TRUE;
lex->current_select->set_with_clause($2);
if (Lex->check_cte_dependencies_and_resolve_references())
MYSQL_YYABORT;
}
;

View File

@ -2056,6 +2056,29 @@ struct vers_select_conds_t
struct LEX;
class Index_hint;
/*
@struct TABLE_CHAIN
@brief Subchain of global chain of table references
The structure contains a pointer to the address of the next_global
pointer to the first TABLE_LIST objectof the subchain and the address
of the next_global pointer to the element right after the last
TABLE_LIST object of the subchain. For an empty subchain both pointers
have the same value.
*/
struct TABLE_CHAIN
{
TABLE_CHAIN() {}
TABLE_LIST **start_pos;
TABLE_LIST ** end_pos;
void set_start_pos(TABLE_LIST **pos) { start_pos= pos; }
void set_end_pos(TABLE_LIST **pos) { end_pos= pos; }
};
struct TABLE_LIST
{
TABLE_LIST() {} /* Remove gcc warning */
@ -2380,6 +2403,20 @@ struct TABLE_LIST
/* call back function for asking handler about caching in query cache */
qc_engine_callback callback_func;
thr_lock_type lock_type;
/*
Two fields below are set during parsing this table reference in the cases
when the table reference can be potentially a reference to a CTE table.
In this cases the fact that the reference is a reference to a CTE or not
will be ascertained at the very end of parsing of the query when referencies
to CTE are resolved. For references to CTE and to derived tables no mdl
requests are needed while for other table references they are. If a request
is possibly postponed the info that allows to issue this request must be
saved in 'mdl_type' and 'table_options'.
*/
enum_mdl_type mdl_type;
ulong table_options;
uint outer_join; /* Which join type */
uint shared; /* Used in multi-upd */
bool updatable; /* VIEW/TABLE can be updated now */

View File

@ -413,11 +413,11 @@ IF(CONNECT_WITH_JDBC AND JAVA_FOUND AND JNI_FOUND)
INSTALL(FILES
${CMAKE_CURRENT_SOURCE_DIR}/mysql-test/connect/std_data/JavaWrappers.jar
${CMAKE_CURRENT_BINARY_DIR}/JdbcInterface.jar
DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT connect-engine)
IF(CONNECT_WITH_MONGO)
INSTALL(FILES
${CMAKE_CURRENT_SOURCE_DIR}/mysql-test/connect/std_data/Mongo2.jar
${CMAKE_CURRENT_SOURCE_DIR}/mysql-test/connect/std_data/Mongo3.jar
DESTINATION ${INSTALL_PLUGINDIR} COMPONENT connect-engine)
DESTINATION ${INSTALL_MYSQLSHAREDIR} COMPONENT connect-engine)
ENDIF()
ENDIF()

View File

@ -57,8 +57,8 @@ extern "C" HINSTANCE s_hModule; // Saved module handle
extern char *JvmPath; // The connect_jvm_path global variable value
extern char *ClassPath; // The connect_class_path global variable value
char *GetPluginDir(void);
char *GetJavaWrapper(void); // The connect_java_wrapper variable value
extern MYSQL_PLUGIN_IMPORT char lc_messages_dir[FN_REFLEN];
/***********************************************************************/
/* Static JAVAConn objects. */
@ -401,23 +401,23 @@ bool JAVAConn::Open(PGLOBAL g)
} // endif ClassPath
#if 0
// Java source will be compiled as a jar file installed in the plugin dir
// Java source will be compiled as a jar file installed in the mysql share dir
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append(lc_messages_dir);
jpop->Append("JdbcInterface.jar");
#endif // 0
// All wrappers are pre-compiled in JavaWrappers.jar in the plugin dir
// All wrappers are pre-compiled in JavaWrappers.jar in the mysql share dir
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append(lc_messages_dir);
jpop->Append("JavaWrappers.jar");
#if defined(MONGO_SUPPORT)
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append(lc_messages_dir);
jpop->Append("Mongo3.jar");
jpop->Append(sep);
jpop->Append(GetPluginDir());
jpop->Append(lc_messages_dir);
jpop->Append("Mongo2.jar");
#endif // MONGO_SUPPORT

View File

@ -1787,7 +1787,6 @@ fts_create_one_common_table(
dict_table_add_system_columns(new_table, heap);
error = row_create_table_for_mysql(new_table, trx,
FIL_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY);
if (error == DB_SUCCESS) {
dict_index_t* index = dict_mem_index_create(
@ -1808,17 +1807,22 @@ fts_create_one_common_table(
error = row_create_index_for_mysql(index, trx, NULL);
trx->dict_operation = op;
} else {
err_exit:
new_table = NULL;
ib::warn() << "Failed to create FTS common table "
<< fts_table_name;
trx->error_state = error;
return NULL;
}
if (error != DB_SUCCESS) {
dict_mem_table_free(new_table);
new_table = NULL;
ib::warn() << "Failed to create FTS common table "
<< fts_table_name;
trx->error_state = DB_SUCCESS;
row_drop_table_for_mysql(fts_table_name, trx, SQLCOM_DROP_DB);
trx->error_state = error;
goto err_exit;
}
return(new_table);
}
@ -1864,6 +1868,8 @@ fts_create_common_tables(
FTS_INIT_FTS_TABLE(&fts_table, NULL, FTS_COMMON_TABLE, table);
op = trx_get_dict_operation(trx);
error = fts_drop_common_tables(trx, &fts_table);
if (error != DB_SUCCESS) {
@ -1879,7 +1885,8 @@ fts_create_common_tables(
dict_table_t* common_table = fts_create_one_common_table(
trx, table, full_name[i], fts_table.suffix, heap);
if (common_table == NULL) {
if (!common_table) {
trx->error_state = DB_SUCCESS;
error = DB_ERROR;
goto func_exit;
} else {
@ -1925,8 +1932,6 @@ fts_create_common_tables(
error = row_create_index_for_mysql(index, trx, NULL);
trx->dict_operation = op;
func_exit:
if (error != DB_SUCCESS) {
for (it = common_tables.begin(); it != common_tables.end();
@ -1936,6 +1941,8 @@ func_exit:
}
}
trx->dict_operation = op;
common_tables.clear();
mem_heap_free(heap);
@ -2019,16 +2026,20 @@ fts_create_one_index_table(
error = row_create_index_for_mysql(index, trx, NULL);
trx->dict_operation = op;
} else {
err_exit:
new_table = NULL;
ib::warn() << "Failed to create FTS index table "
<< table_name;
trx->error_state = error;
return NULL;
}
if (error != DB_SUCCESS) {
dict_mem_table_free(new_table);
new_table = NULL;
ib::warn() << "Failed to create FTS index table "
<< table_name;
trx->error_state = DB_SUCCESS;
row_drop_table_for_mysql(table_name, trx, SQLCOM_DROP_DB);
trx->error_state = error;
goto err_exit;
}
return(new_table);

View File

@ -6367,7 +6367,9 @@ no_such_table:
/* Index block size in InnoDB: used by MySQL in query optimization */
stats.block_size = srv_page_size;
if (m_prebuilt->table == NULL
const my_bool for_vc_purge = THDVAR(thd, background_thread);
if (for_vc_purge || !m_prebuilt->table
|| m_prebuilt->table->is_temporary()
|| m_prebuilt->table->persistent_autoinc
|| !m_prebuilt->table->is_readable()) {
@ -6394,7 +6396,7 @@ no_such_table:
ut_ad(!m_prebuilt->table
|| table->versioned() == m_prebuilt->table->versioned());
if (!THDVAR(thd, background_thread)) {
if (!for_vc_purge) {
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST
| HA_STATUS_OPEN);
}
@ -12834,7 +12836,6 @@ create_table_info_t::create_table_update_dict()
if (!innobase_fts_load_stopword(innobase_table, NULL, m_thd)) {
dict_table_close(innobase_table, FALSE, FALSE);
srv_active_wake_master_thread();
m_trx->free();
DBUG_RETURN(-1);
}
@ -12961,19 +12962,12 @@ ha_innobase::create(
}
trx_rollback_for_mysql(trx);
row_mysql_unlock_data_dictionary(trx);
if (own_trx) {
trx->free();
}
DBUG_RETURN(error);
goto func_exit;
}
innobase_commit_low(trx);
row_mysql_unlock_data_dictionary(trx);
if (own_trx) {
trx->free();
}
/* Flush the log to reduce probability that the .frm files and
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
@ -12983,6 +12977,11 @@ ha_innobase::create(
error = info.create_table_update_dict();
func_exit:
if (own_trx) {
trx->free();
}
/* Tell the InnoDB server that there might be work for
utility threads: */

View File

@ -588,14 +588,13 @@ else()
set(GRN_WITH_MESSAGE_PACK FALSE)
endif()
find_program(RUBY NAMES
"ruby2.3" "ruby23"
"ruby2.2" "ruby22"
"ruby2.1" "ruby21"
"ruby")
option(GRN_WITH_MRUBY "use mruby" OFF)
if(GRN_WITH_MRUBY)
find_program(RUBY NAMES
"ruby2.3" "ruby23"
"ruby2.2" "ruby22"
"ruby2.1" "ruby21"
"ruby")
set(MRUBY_INCLUDE_DIRS
"${CMAKE_CURRENT_SOURCE_DIR}/vendor/mruby-source/include")
set(MRUBY_LIBS mruby)