1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-05 13:16:09 +03:00

Additional merge to lp:maria/10.0

This commit is contained in:
Jan Lindström
2014-03-04 18:56:18 +02:00
47 changed files with 540 additions and 198 deletions

View File

@@ -153,6 +153,7 @@ INCLUDE(readline)
INCLUDE(libutils) INCLUDE(libutils)
INCLUDE(dtrace) INCLUDE(dtrace)
INCLUDE(jemalloc) INCLUDE(jemalloc)
INCLUDE(pcre)
INCLUDE(ctest) INCLUDE(ctest)
INCLUDE(plugin) INCLUDE(plugin)
INCLUDE(install_macros) INCLUDE(install_macros)
@@ -362,6 +363,8 @@ MYSQL_CHECK_READLINE()
SET(MALLOC_LIBRARY "system") SET(MALLOC_LIBRARY "system")
CHECK_JEMALLOC() CHECK_JEMALLOC()
CHECK_PCRE()
# #
# Setup maintainer mode options. Platform checks are # Setup maintainer mode options. Platform checks are
# not run with the warning options as to not perturb fragile checks # not run with the warning options as to not perturb fragile checks
@@ -397,7 +400,6 @@ ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(dbug) ADD_SUBDIRECTORY(dbug)
ADD_SUBDIRECTORY(strings) ADD_SUBDIRECTORY(strings)
ADD_SUBDIRECTORY(vio) ADD_SUBDIRECTORY(vio)
ADD_SUBDIRECTORY(pcre)
ADD_SUBDIRECTORY(mysys) ADD_SUBDIRECTORY(mysys)
ADD_SUBDIRECTORY(mysys_ssl) ADD_SUBDIRECTORY(mysys_ssl)
ADD_SUBDIRECTORY(libmysql) ADD_SUBDIRECTORY(libmysql)

View File

@@ -15,8 +15,7 @@
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${CMAKE_SOURCE_DIR}/mysys_ssl ${CMAKE_SOURCE_DIR}/mysys_ssl
${ZLIB_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}
${SSL_INCLUDE_DIRS} ${SSL_INCLUDE_DIRS}

View File

@@ -46,7 +46,7 @@ ELSE()
ENDIF() ENDIF()
SET(WITH_JEMALLOC ${WITH_JEMALLOC_DEFAULT} CACHE STRING SET(WITH_JEMALLOC ${WITH_JEMALLOC_DEFAULT} CACHE STRING
"Which jemalloc to use (possible values are 'no', 'bundled', 'system', 'yes' (system if possible, otherwise bundled)") "Which jemalloc to use. Possible values are 'no', 'bundled', 'system', 'yes' (system if possible, otherwise bundled)")
MACRO (CHECK_JEMALLOC) MACRO (CHECK_JEMALLOC)
IF(WITH_JEMALLOC STREQUAL "system" OR WITH_JEMALLOC STREQUAL "yes") IF(WITH_JEMALLOC STREQUAL "system" OR WITH_JEMALLOC STREQUAL "yes")

16
cmake/pcre.cmake Normal file
View File

@@ -0,0 +1,16 @@
SET(WITH_PCRE "auto" CACHE STRING
"Which pcre to use (possible values are 'bundled', 'system', or 'auto')")
MACRO (CHECK_PCRE)
IF(WITH_PCRE STREQUAL "system" OR WITH_PCRE STREQUAL "auto")
CHECK_LIBRARY_EXISTS(pcre pcre_stack_guard "" HAVE_PCRE)
ENDIF()
IF(NOT HAVE_PCRE)
IF (WITH_PCRE STREQUAL "system")
MESSAGE(FATAL_ERROR "system pcre is not found or unusable")
ENDIF()
SET(PCRE_INCLUDES ${CMAKE_BINARY_DIR}/pcre ${CMAKE_SOURCE_DIR}/pcre)
ADD_SUBDIRECTORY(pcre)
ENDIF()
ENDMACRO()

View File

@@ -37,8 +37,7 @@ MACRO(MYSQL_ADD_PLUGIN)
# Add common include directories # Add common include directories
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/sql
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${SSL_INCLUDE_DIRS} ${SSL_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIR}) ${ZLIB_INCLUDE_DIR})

View File

@@ -17,8 +17,7 @@
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/libmysql ${CMAKE_SOURCE_DIR}/libmysql
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${CMAKE_SOURCE_DIR}/strings ${CMAKE_SOURCE_DIR}/strings
${SSL_INCLUDE_DIRS} ${SSL_INCLUDE_DIRS}
${SSL_INTERNAL_INCLUDE_DIRS} ${SSL_INTERNAL_INCLUDE_DIRS}

View File

@@ -22,8 +22,7 @@ ${CMAKE_SOURCE_DIR}/libmysql
${CMAKE_SOURCE_DIR}/libmysqld ${CMAKE_SOURCE_DIR}/libmysqld
${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/sql
${CMAKE_BINARY_DIR}/sql ${CMAKE_BINARY_DIR}/sql
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${ZLIB_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}
${SSL_INCLUDE_DIRS} ${SSL_INCLUDE_DIRS}
${SSL_INTERNAL_INCLUDE_DIRS} ${SSL_INTERNAL_INCLUDE_DIRS}

View File

@@ -15,8 +15,7 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/libmysqld/include ${CMAKE_SOURCE_DIR}/libmysqld/include
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/sql
${MY_READLINE_INCLUDE_DIR} ${MY_READLINE_INCLUDE_DIR}
) )

View File

@@ -127,7 +127,7 @@ drop table t1;
SET @OLD_SQL_MODE=@@SQL_MODE; SET @OLD_SQL_MODE=@@SQL_MODE;
SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS'; SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS';
#illegal value fixed #illegal value fixed
CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS; CREATE TABLE t1 (a int, b int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
Warnings: Warnings:
Warning 1912 Incorrect value '10000000000000000000' for option 'ULL' Warning 1912 Incorrect value '10000000000000000000' for option 'ULL'
Warning 1912 Incorrect value 'ttt' for option 'one_or_two' Warning 1912 Incorrect value 'ttt' for option 'one_or_two'
@@ -135,7 +135,8 @@ Warning 1912 Incorrect value 'SSS' for option 'YESNO'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `ULL`=10000000000000000000 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5'
#alter table #alter table
alter table t1 ULL=10000000; alter table t1 ULL=10000000;
@@ -144,7 +145,8 @@ Note 1105 EXAMPLE DEBUG: ULL 4294967290 -> 10000000
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' `ULL`=10000000 ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' `ULL`=10000000
alter table t1 change a a int complex='c,c,c'; alter table t1 change a a int complex='c,c,c';
Warnings: Warnings:
@@ -152,15 +154,15 @@ Note 1105 EXAMPLE DEBUG: Field `a` COMPLEX '(null)' -> 'c,c,c'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `complex`='c,c,c' `a` int(11) DEFAULT NULL `complex`='c,c,c',
`b` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' `ULL`=10000000 ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `one_or_two`='ttt' `YESNO`=SSS `VAROPT`='5' `ULL`=10000000
alter table t1 one_or_two=two; alter table t1 one_or_two=two;
Warnings:
Note 1105 EXAMPLE DEBUG: Field `a` COMPLEX 'c,c,c' -> 'c,c,c'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `complex`='c,c,c' `a` int(11) DEFAULT NULL `complex`='c,c,c',
`b` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `YESNO`=SSS `VAROPT`='5' `ULL`=10000000 `one_or_two`=two ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `YESNO`=SSS `VAROPT`='5' `ULL`=10000000 `one_or_two`=two
drop table t1; drop table t1;
#illegal value error #illegal value error
@@ -204,8 +206,6 @@ t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL `a` int(11) DEFAULT NULL
) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `varopt`=15 ) ENGINE=EXAMPLE DEFAULT CHARSET=latin1 `varopt`=15
alter table t1 varopt=default; alter table t1 varopt=default;
Warnings:
Note 1105 EXAMPLE DEBUG: Field `a` COMPLEX '(null)' -> '(null)'
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (

Binary file not shown.

View File

@@ -1,3 +1,5 @@
grant '' to foo@localhost;
ERROR OP000: Invalid role specification ``.
create user ''@localhost; create user ''@localhost;
create role r1; create role r1;
grant r1 to ''@localhost; grant r1 to ''@localhost;

View File

@@ -1,3 +1,9 @@
#
# MDEV-5668 Assertion `granted_role->is_role()' fails on granting role with empty name
#
--error ER_INVALID_ROLE
grant '' to foo@localhost;
# #
# MDEV-5238 Server crashes in find_role_grant_pair on SHOW GRANTS for an anonymous user # MDEV-5238 Server crashes in find_role_grant_pair on SHOW GRANTS for an anonymous user
# #

View File

@@ -62,6 +62,32 @@ slave-relay-bin.000007 # Query # # # Dummy ev
slave-relay-bin.000007 # Table_map # # table_id: # (test.t1) slave-relay-bin.000007 # Table_map # # table_id: # (test.t1)
slave-relay-bin.000007 # Write_rows_v1 # # table_id: # flags: STMT_END_F slave-relay-bin.000007 # Write_rows_v1 # # table_id: # flags: STMT_END_F
slave-relay-bin.000007 # Query # # COMMIT slave-relay-bin.000007 # Query # # COMMIT
*** MDEV-5754: MySQL 5.5 slaves cannot replicate from MariaDB 10.0 ***
CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
INSERT INTO t2 VALUES (1);
SET debug_sync='now WAIT_FOR master_queued1';
SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
INSERT INTO t2 VALUES (2);
SET debug_sync='now WAIT_FOR master_queued2';
SET debug_sync='now SIGNAL master_cont1';
SET debug_sync='RESET';
SET debug_sync='RESET';
SET debug_sync='RESET';
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
master-bin.000003 # Table_map # # table_id: # (test.t2)
master-bin.000003 # Write_rows_v1 # # table_id: # flags: STMT_END_F
master-bin.000003 # Xid # # COMMIT /* XID */
master-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
master-bin.000003 # Table_map # # table_id: # (test.t2)
master-bin.000003 # Write_rows_v1 # # table_id: # flags: STMT_END_F
master-bin.000003 # Xid # # COMMIT /* XID */
SELECT * FROM t2 ORDER BY a;
a
1
2
# Test that slave which cannot tolerate holes in binlog stream but # Test that slave which cannot tolerate holes in binlog stream but
# knows the event does not get dummy event # knows the event does not get dummy event
include/stop_slave.inc include/stop_slave.inc
@@ -95,5 +121,5 @@ select @@global.replicate_annotate_row_events;
set @@global.debug_dbug= @old_slave_dbug; set @@global.debug_dbug= @old_slave_dbug;
Clean up. Clean up.
set @@global.binlog_checksum = @old_master_binlog_checksum; set @@global.binlog_checksum = @old_master_binlog_checksum;
DROP TABLE t1; DROP TABLE t1, t2;
include/rpl_end.inc include/rpl_end.inc

View File

@@ -0,0 +1,27 @@
include/master-slave.inc
[connection master]
include/stop_slave.inc
include/rpl_stop_server.inc [server_number=1]
include/rpl_start_server.inc [server_number=1]
SET @old_parallel= @@GLOBAL.slave_parallel_threads;
SET GLOBAL slave_parallel_threads=10;
CHANGE MASTER TO master_host='127.0.0.1', master_port=SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4;
include/start_slave.inc
CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t2 VALUES (1);
SELECT * FROM t1 ORDER BY a;
a b
1 1
2 2
3 4
4 8
5 16
SELECT * FROM t2;
a
1
include/stop_slave.inc
SET GLOBAL slave_parallel_threads=@old_parallel;
DROP TABLE t1;
include/start_slave.inc
DROP TABLE t2;
include/rpl_end.inc

View File

@@ -1,6 +1,8 @@
--source include/master-slave.inc --source include/master-slave.inc
--source include/have_debug.inc --source include/have_debug.inc
--source include/have_debug_sync.inc
--source include/have_binlog_format_row.inc --source include/have_binlog_format_row.inc
--source include/have_innodb.inc
connection master; connection master;
@@ -71,6 +73,52 @@ let $binlog_start= 0;
let $binlog_limit=7,5; let $binlog_limit=7,5;
--source include/show_relaylog_events.inc --source include/show_relaylog_events.inc
--echo *** MDEV-5754: MySQL 5.5 slaves cannot replicate from MariaDB 10.0 ***
# The problem was that for a group commit, we get commit id into the
# GTID event, and there was a bug in the code that replaces GTID with
# dummy that failed when commit id was present.
#
# So setup a group commit in InnoDB.
--connection master
CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
send INSERT INTO t2 VALUES (1);
--connection master
SET debug_sync='now WAIT_FOR master_queued1';
--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
send INSERT INTO t2 VALUES (2);
--connection master
SET debug_sync='now WAIT_FOR master_queued2';
SET debug_sync='now SIGNAL master_cont1';
--connection con1
REAP;
SET debug_sync='RESET';
--connection con2
REAP;
SET debug_sync='RESET';
--connection master
SET debug_sync='RESET';
let $binlog_limit= 0, 8;
--source include/show_binlog_events.inc
--save_master_pos
--connection slave
--sync_with_master
SELECT * FROM t2 ORDER BY a;
--echo # Test that slave which cannot tolerate holes in binlog stream but --echo # Test that slave which cannot tolerate holes in binlog stream but
--echo # knows the event does not get dummy event --echo # knows the event does not get dummy event
@@ -106,6 +154,6 @@ set @@global.debug_dbug= @old_slave_dbug;
--echo Clean up. --echo Clean up.
connection master; connection master;
set @@global.binlog_checksum = @old_master_binlog_checksum; set @@global.binlog_checksum = @old_master_binlog_checksum;
DROP TABLE t1; DROP TABLE t1, t2;
sync_slave_with_master; sync_slave_with_master;
--source include/rpl_end.inc --source include/rpl_end.inc

View File

@@ -0,0 +1,49 @@
# Test replicating off old master.
# We simulate old master by copying in pre-generated binlog files from earlier
# server versions.
--source include/have_innodb.inc
--source include/master-slave.inc
--connection slave
--source include/stop_slave.inc
--connection master
--let $datadir= `SELECT @@datadir`
--let $rpl_server_number= 1
--source include/rpl_stop_server.inc
--remove_file $datadir/master-bin.000001
--copy_file $MYSQL_TEST_DIR/std_data/mariadb-5.5-binlog.000001 $datadir/master-bin.000001
--let $rpl_server_number= 1
--source include/rpl_start_server.inc
--source include/wait_until_connected_again.inc
--connection slave
SET @old_parallel= @@GLOBAL.slave_parallel_threads;
SET GLOBAL slave_parallel_threads=10;
--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1, master_user='root', master_log_file='master-bin.000001', master_log_pos=4;
--source include/start_slave.inc
--connection master
CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t2 VALUES (1);
--save_master_pos
--connection slave
--sync_with_master
SELECT * FROM t1 ORDER BY a;
SELECT * FROM t2;
--source include/stop_slave.inc
SET GLOBAL slave_parallel_threads=@old_parallel;
DROP TABLE t1;
--source include/start_slave.inc
--connection master
DROP TABLE t2;
--source include/rpl_end.inc

View File

@@ -121,7 +121,7 @@ SET @OLD_SQL_MODE=@@SQL_MODE;
SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS'; SET SQL_MODE='IGNORE_BAD_TABLE_OPTIONS';
--echo #illegal value fixed --echo #illegal value fixed
CREATE TABLE t1 (a int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS; CREATE TABLE t1 (a int, b int) ENGINE=example ULL=10000000000000000000 one_or_two='ttt' YESNO=SSS;
show create table t1; show create table t1;
--echo #alter table --echo #alter table

View File

@@ -1,6 +1,5 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${SSL_INCLUDE_DIRS}) ${SSL_INCLUDE_DIRS})
SET(FEEDBACK_SOURCES feedback.cc sender_thread.cc SET(FEEDBACK_SOURCES feedback.cc sender_thread.cc

View File

@@ -1,6 +1,5 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${CMAKE_SOURCE_DIR}/extra/yassl/include) ${CMAKE_SOURCE_DIR}/extra/yassl/include)
MYSQL_ADD_PLUGIN(QUERY_CACHE_INFO qc_info.cc) MYSQL_ADD_PLUGIN(QUERY_CACHE_INFO qc_info.cc)

View File

@@ -16,8 +16,7 @@
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/sql
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${ZLIB_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}
${SSL_INCLUDE_DIRS} ${SSL_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}/sql ${CMAKE_BINARY_DIR}/sql

View File

@@ -188,6 +188,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
my_b_clear(&buffpek_pointers); my_b_clear(&buffpek_pointers);
buffpek=0; buffpek=0;
error= 1; error= 1;
*found_rows= HA_POS_ERROR;
param.init_for_filesort(sortlength(thd, sortorder, s_length, param.init_for_filesort(sortlength(thd, sortorder, s_length,
&multi_byte_charset), &multi_byte_charset),

View File

@@ -4123,6 +4123,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH | Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH |
Alter_inplace_info::ALTER_COLUMN_NAME | Alter_inplace_info::ALTER_COLUMN_NAME |
Alter_inplace_info::ALTER_COLUMN_DEFAULT | Alter_inplace_info::ALTER_COLUMN_DEFAULT |
Alter_inplace_info::ALTER_COLUMN_OPTION |
Alter_inplace_info::CHANGE_CREATE_OPTION | Alter_inplace_info::CHANGE_CREATE_OPTION |
Alter_inplace_info::ALTER_RENAME; Alter_inplace_info::ALTER_RENAME;

View File

@@ -1740,8 +1740,11 @@ public:
// Table is renamed // Table is renamed
static const HA_ALTER_FLAGS ALTER_RENAME = 1L << 18; static const HA_ALTER_FLAGS ALTER_RENAME = 1L << 18;
// Change the storage type of column // column's engine options changed, something in field->option_struct
static const HA_ALTER_FLAGS ALTER_COLUMN_STORAGE_TYPE = 1L << 19; static const HA_ALTER_FLAGS ALTER_COLUMN_OPTION = 1L << 19;
// MySQL alias for the same thing:
static const HA_ALTER_FLAGS ALTER_COLUMN_STORAGE_TYPE = 1L << 19;
// Change the column format of column // Change the column format of column
static const HA_ALTER_FLAGS ALTER_COLUMN_COLUMN_FORMAT = 1L << 20; static const HA_ALTER_FLAGS ALTER_COLUMN_COLUMN_FORMAT = 1L << 20;
@@ -1770,7 +1773,7 @@ public:
// Partition operation with ALL keyword // Partition operation with ALL keyword
static const HA_ALTER_FLAGS ALTER_ALL_PARTITION = 1L << 28; static const HA_ALTER_FLAGS ALTER_ALL_PARTITION = 1L << 28;
// Partition operation with ALL keyword // Virtual columns changed
static const HA_ALTER_FLAGS ALTER_COLUMN_VCOL = 1L << 29; static const HA_ALTER_FLAGS ALTER_COLUMN_VCOL = 1L << 29;
/** /**

View File

@@ -3736,9 +3736,14 @@ Query_log_event::begin_event(String *packet, ulong ev_offset,
DBUG_ASSERT(checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF || DBUG_ASSERT(checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF ||
checksum_alg == BINLOG_CHECKSUM_ALG_OFF); checksum_alg == BINLOG_CHECKSUM_ALG_OFF);
/* Currently we only need to replace GTID event. */ /*
DBUG_ASSERT(data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN); Currently we only need to replace GTID event.
if (data_len != LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN) The length of GTID differs depending on whether it contains commit id.
*/
DBUG_ASSERT(data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN ||
data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN + 2);
if (data_len != LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN &&
data_len != LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN + 2)
return 1; return 1;
flags= uint2korr(p + FLAGS_OFFSET); flags= uint2korr(p + FLAGS_OFFSET);
@@ -3751,9 +3756,22 @@ Query_log_event::begin_event(String *packet, ulong ev_offset,
int4store(q + Q_EXEC_TIME_OFFSET, 0); int4store(q + Q_EXEC_TIME_OFFSET, 0);
q[Q_DB_LEN_OFFSET]= 0; q[Q_DB_LEN_OFFSET]= 0;
int2store(q + Q_ERR_CODE_OFFSET, 0); int2store(q + Q_ERR_CODE_OFFSET, 0);
int2store(q + Q_STATUS_VARS_LEN_OFFSET, 0); if (data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN)
q[Q_DATA_OFFSET]= 0; /* Zero terminator for empty db */ {
q+= Q_DATA_OFFSET + 1; int2store(q + Q_STATUS_VARS_LEN_OFFSET, 0);
q[Q_DATA_OFFSET]= 0; /* Zero terminator for empty db */
q+= Q_DATA_OFFSET + 1;
}
else
{
DBUG_ASSERT(data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN + 2);
/* Put in an empty time_zone_str to take up the extra 2 bytes. */
int2store(q + Q_STATUS_VARS_LEN_OFFSET, 2);
q[Q_DATA_OFFSET]= Q_TIME_ZONE_CODE;
q[Q_DATA_OFFSET+1]= 0; /* Zero length for empty time_zone_str */
q[Q_DATA_OFFSET+2]= 0; /* Zero terminator for empty db */
q+= Q_DATA_OFFSET + 3;
}
memcpy(q, "BEGIN", 5); memcpy(q, "BEGIN", 5);
if (checksum_alg == BINLOG_CHECKSUM_ALG_CRC32) if (checksum_alg == BINLOG_CHECKSUM_ALG_CRC32)
@@ -6779,7 +6797,7 @@ Gtid_list_log_event::write(IO_CACHE *file)
int int
Gtid_list_log_event::do_apply_event(rpl_group_info *rgi) Gtid_list_log_event::do_apply_event(rpl_group_info *rgi)
{ {
Relay_log_info const *rli= rgi->rli; Relay_log_info *rli= const_cast<Relay_log_info*>(rgi->rli);
int ret; int ret;
if (gl_flags & FLAG_IGN_GTIDS) if (gl_flags & FLAG_IGN_GTIDS)
{ {
@@ -6799,10 +6817,11 @@ Gtid_list_log_event::do_apply_event(rpl_group_info *rgi)
{ {
char str_buf[128]; char str_buf[128];
String str(str_buf, sizeof(str_buf), system_charset_info); String str(str_buf, sizeof(str_buf), system_charset_info);
const_cast<Relay_log_info*>(rli)->until_gtid_pos.to_string(&str); rli->until_gtid_pos.to_string(&str);
sql_print_information("Slave SQL thread stops because it reached its" sql_print_information("Slave SQL thread stops because it reached its"
" UNTIL master_gtid_pos %s", str.c_ptr_safe()); " UNTIL master_gtid_pos %s", str.c_ptr_safe());
const_cast<Relay_log_info*>(rli)->abort_slave= true; rli->abort_slave= true;
rli->stop_for_until= true;
} }
return ret; return ret;
} }

View File

@@ -3123,12 +3123,15 @@ public:
<td>flags</td> <td>flags</td>
<td>1 byte bitfield</td> <td>1 byte bitfield</td>
<td>Bit 0 set indicates stand-alone event (no terminating COMMIT)</td> <td>Bit 0 set indicates stand-alone event (no terminating COMMIT)</td>
<td>Bit 1 set indicates group commit, and that commit id exists</td>
</tr> </tr>
<tr> <tr>
<td>Reserved</td> <td>Reserved (no group commit) / commit id (group commit) (see flags bit 1)</td>
<td>6 bytes</td> <td>6 bytes / 8 bytes</td>
<td>Reserved bytes, set to 0. Maybe be used for future expansion.</td> <td>Reserved bytes, set to 0. Maybe be used for future expansion (no
group commit). OR commit id, same for all GTIDs in the same group
commit (see flags bit 1).</td>
</tr> </tr>
</table> </table>

View File

@@ -173,6 +173,7 @@ signal_error_to_sql_driver_thread(THD *thd, rpl_group_info *rgi)
rgi->is_error= true; rgi->is_error= true;
rgi->cleanup_context(thd, true); rgi->cleanup_context(thd, true);
rgi->rli->abort_slave= true; rgi->rli->abort_slave= true;
rgi->rli->stop_for_until= false;
mysql_mutex_lock(rgi->rli->relay_log.get_log_lock()); mysql_mutex_lock(rgi->rli->relay_log.get_log_lock());
mysql_mutex_unlock(rgi->rli->relay_log.get_log_lock()); mysql_mutex_unlock(rgi->rli->relay_log.get_log_lock());
rgi->rli->relay_log.signal_update(); rgi->rli->relay_log.signal_update();
@@ -1122,7 +1123,7 @@ rpl_parallel::find(uint32 domain_id)
void void
rpl_parallel::wait_for_done(THD *thd) rpl_parallel::wait_for_done(THD *thd, Relay_log_info *rli)
{ {
struct rpl_parallel_entry *e; struct rpl_parallel_entry *e;
rpl_parallel_thread *rpt; rpl_parallel_thread *rpt;
@@ -1152,9 +1153,13 @@ rpl_parallel::wait_for_done(THD *thd)
started executing yet. So we set e->stop_count here and use it to started executing yet. So we set e->stop_count here and use it to
decide in the worker threads whether to continue executing an event decide in the worker threads whether to continue executing an event
group or whether to skip it, when force_abort is set. group or whether to skip it, when force_abort is set.
If we stop due to reaching the START SLAVE UNTIL condition, then we
need to continue executing any queued events up to that point.
*/ */
e->force_abort= true; e->force_abort= true;
e->stop_count= e->count_committing_event_groups; e->stop_count= rli->stop_for_until ?
e->count_queued_event_groups : e->count_committing_event_groups;
mysql_mutex_unlock(&e->LOCK_parallel_entry); mysql_mutex_unlock(&e->LOCK_parallel_entry);
for (j= 0; j < e->rpl_thread_max; ++j) for (j= 0; j < e->rpl_thread_max; ++j)
{ {
@@ -1190,6 +1195,30 @@ rpl_parallel::wait_for_done(THD *thd)
} }
/*
This function handles the case where the SQL driver thread reached the
START SLAVE UNTIL position; we stop queueing more events but continue
processing remaining, already queued events; then use executes manual
STOP SLAVE; then this function signals to worker threads that they
should stop the processing of any remaining queued events.
*/
void
rpl_parallel::stop_during_until()
{
struct rpl_parallel_entry *e;
uint32 i;
for (i= 0; i < domain_hash.records; ++i)
{
e= (struct rpl_parallel_entry *)my_hash_element(&domain_hash, i);
mysql_mutex_lock(&e->LOCK_parallel_entry);
if (e->force_abort)
e->stop_count= e->count_committing_event_groups;
mysql_mutex_unlock(&e->LOCK_parallel_entry);
}
}
bool bool
rpl_parallel::workers_idle() rpl_parallel::workers_idle()
{ {
@@ -1230,11 +1259,12 @@ abandon_worker_thread(THD *thd, rpl_parallel_thread *cur_thread,
do_event() is executed by the sql_driver_thd thread. do_event() is executed by the sql_driver_thd thread.
It's main purpose is to find a thread that can execute the query. It's main purpose is to find a thread that can execute the query.
@retval false ok, event was accepted @retval 0 ok, event was accepted
@retval true error @retval 1 error
@retval -1 event should be executed serially, in the sql driver thread
*/ */
bool int
rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev, rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
ulonglong event_size) ulonglong event_size)
{ {
@@ -1248,6 +1278,32 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
bool did_enter_cond= false; bool did_enter_cond= false;
PSI_stage_info old_stage; PSI_stage_info old_stage;
/* Handle master log name change, seen in Rotate_log_event. */
typ= ev->get_type_code();
if (unlikely(typ == ROTATE_EVENT))
{
Rotate_log_event *rev= static_cast<Rotate_log_event *>(ev);
if ((rev->server_id != global_system_variables.server_id ||
rli->replicate_same_server_id) &&
!rev->is_relay_log_event() &&
!rli->is_in_group())
{
memcpy(rli->future_event_master_log_name,
rev->new_log_ident, rev->ident_len+1);
}
}
/*
Execute queries non-parallel if slave_skip_counter is set, as it's is
easier to skip queries in single threaded mode.
*/
if (rli->slave_skip_counter)
return -1;
/* Execute pre-10.0 event, which have no GTID, in single-threaded mode. */
if (unlikely(!current) && typ != GTID_EVENT)
return -1;
/* ToDo: what to do with this lock?!? */ /* ToDo: what to do with this lock?!? */
mysql_mutex_unlock(&rli->data_lock); mysql_mutex_unlock(&rli->data_lock);
@@ -1259,21 +1315,20 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
been partially queued, but after that we will just ignore any further been partially queued, but after that we will just ignore any further
events the SQL driver thread may try to queue, and eventually it will stop. events the SQL driver thread may try to queue, and eventually it will stop.
*/ */
if (((typ= ev->get_type_code()) == GTID_EVENT || is_group_event= Log_event::is_group_event(typ);
!(is_group_event= Log_event::is_group_event(typ))) && if ((typ == GTID_EVENT || !is_group_event) && rli->abort_slave)
rli->abort_slave)
sql_thread_stopping= true; sql_thread_stopping= true;
if (sql_thread_stopping) if (sql_thread_stopping)
{ {
delete ev; delete ev;
/* /*
Return false ("no error"); normal stop is not an error, and otherwise the Return "no error"; normal stop is not an error, and otherwise the error
error has already been recorded. has already been recorded.
*/ */
return false; return 0;
} }
if (typ == GTID_EVENT || unlikely(!current)) if (typ == GTID_EVENT)
{ {
uint32 domain_id; uint32 domain_id;
if (likely(typ == GTID_EVENT)) if (likely(typ == GTID_EVENT))
@@ -1288,7 +1343,7 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
{ {
my_error(ER_OUT_OF_RESOURCES, MYF(MY_WME)); my_error(ER_OUT_OF_RESOURCES, MYF(MY_WME));
delete ev; delete ev;
return true; return 1;
} }
current= e; current= e;
} }
@@ -1307,7 +1362,7 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
{ {
/* This means we were killed. The error is already signalled. */ /* This means we were killed. The error is already signalled. */
delete ev; delete ev;
return true; return 1;
} }
if (!(qev= cur_thread->get_qev(ev, event_size, rli))) if (!(qev= cur_thread->get_qev(ev, event_size, rli)))
@@ -1315,7 +1370,7 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
abandon_worker_thread(rli->sql_driver_thd, cur_thread, abandon_worker_thread(rli->sql_driver_thd, cur_thread,
&did_enter_cond, &old_stage); &did_enter_cond, &old_stage);
delete ev; delete ev;
return true; return 1;
} }
if (typ == GTID_EVENT) if (typ == GTID_EVENT)
@@ -1328,7 +1383,7 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
abandon_worker_thread(rli->sql_driver_thd, cur_thread, abandon_worker_thread(rli->sql_driver_thd, cur_thread,
&did_enter_cond, &old_stage); &did_enter_cond, &old_stage);
delete ev; delete ev;
return true; return 1;
} }
/* /*
@@ -1366,7 +1421,7 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
abandon_worker_thread(rli->sql_driver_thd, cur_thread, abandon_worker_thread(rli->sql_driver_thd, cur_thread,
&did_enter_cond, &old_stage); &did_enter_cond, &old_stage);
delete ev; delete ev;
return true; return 1;
} }
e->current_gco= rgi->gco= gco; e->current_gco= rgi->gco= gco;
} }
@@ -1380,7 +1435,7 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
e->current_sub_id= rgi->gtid_sub_id; e->current_sub_id= rgi->gtid_sub_id;
++e->count_queued_event_groups; ++e->count_queued_event_groups;
} }
else if (!is_group_event || !e) else if (!is_group_event)
{ {
my_off_t log_pos; my_off_t log_pos;
int err; int err;
@@ -1389,38 +1444,22 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
Events like ROTATE and FORMAT_DESCRIPTION. Do not run in worker thread. Events like ROTATE and FORMAT_DESCRIPTION. Do not run in worker thread.
Same for events not preceeded by GTID (we should not see those normally, Same for events not preceeded by GTID (we should not see those normally,
but they might be from an old master). but they might be from an old master).
The variable `e' is NULL for the case where the master did not
have GTID, like a MariaDB 5.5 or MySQL master.
*/ */
qev->rgi= serial_rgi; qev->rgi= serial_rgi;
/* Handle master log name change, seen in Rotate_log_event. */
if (typ == ROTATE_EVENT)
{
Rotate_log_event *rev= static_cast<Rotate_log_event *>(qev->ev);
if ((rev->server_id != global_system_variables.server_id ||
rli->replicate_same_server_id) &&
!rev->is_relay_log_event() &&
!rli->is_in_group())
{
memcpy(rli->future_event_master_log_name,
rev->new_log_ident, rev->ident_len+1);
}
}
tmp= serial_rgi->is_parallel_exec; tmp= serial_rgi->is_parallel_exec;
serial_rgi->is_parallel_exec= true; serial_rgi->is_parallel_exec= true;
err= rpt_handle_event(qev, NULL); err= rpt_handle_event(qev, NULL);
serial_rgi->is_parallel_exec= tmp; serial_rgi->is_parallel_exec= tmp;
log_pos= qev->ev->log_pos; log_pos= ev->log_pos;
delete_or_keep_event_post_apply(serial_rgi, typ, qev->ev); delete_or_keep_event_post_apply(serial_rgi, typ, ev);
if (err) if (err)
{ {
cur_thread->free_qev(qev); cur_thread->free_qev(qev);
abandon_worker_thread(rli->sql_driver_thd, cur_thread, abandon_worker_thread(rli->sql_driver_thd, cur_thread,
&did_enter_cond, &old_stage); &did_enter_cond, &old_stage);
return true; return 1;
} }
/* /*
Queue an empty event, so that the position will be updated in a Queue an empty event, so that the position will be updated in a
@@ -1451,5 +1490,5 @@ rpl_parallel::do_event(rpl_group_info *serial_rgi, Log_event *ev,
&did_enter_cond, &old_stage); &did_enter_cond, &old_stage);
mysql_cond_signal(&cur_thread->COND_rpl_thread); mysql_cond_signal(&cur_thread->COND_rpl_thread);
return false; return 0;
} }

View File

@@ -222,10 +222,10 @@ struct rpl_parallel {
~rpl_parallel(); ~rpl_parallel();
void reset(); void reset();
rpl_parallel_entry *find(uint32 domain_id); rpl_parallel_entry *find(uint32 domain_id);
void wait_for_done(THD *thd); void wait_for_done(THD *thd, Relay_log_info *rli);
void stop_during_until();
bool workers_idle(); bool workers_idle();
bool do_event(rpl_group_info *serial_rgi, Log_event *ev, int do_event(rpl_group_info *serial_rgi, Log_event *ev, ulonglong event_size);
ulonglong event_size);
}; };

View File

@@ -60,7 +60,8 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery)
group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0), group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0),
last_master_timestamp(0), sql_thread_caught_up(true), slave_skip_counter(0), last_master_timestamp(0), sql_thread_caught_up(true), slave_skip_counter(0),
abort_pos_wait(0), slave_run_id(0), sql_driver_thd(), abort_pos_wait(0), slave_run_id(0), sql_driver_thd(),
inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE), inited(0), abort_slave(0), stop_for_until(0),
slave_running(0), until_condition(UNTIL_NONE),
until_log_pos(0), retried_trans(0), executed_entries(0), until_log_pos(0), retried_trans(0), executed_entries(0),
m_flags(0) m_flags(0)
{ {

View File

@@ -262,6 +262,7 @@ public:
*/ */
volatile bool inited; volatile bool inited;
volatile bool abort_slave; volatile bool abort_slave;
volatile bool stop_for_until;
volatile uint slave_running; volatile uint slave_running;
/* /*

View File

@@ -615,7 +615,14 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock)
if (thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL)) if (thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL))
{ {
DBUG_PRINT("info",("Terminating SQL thread")); DBUG_PRINT("info",("Terminating SQL thread"));
mi->rli.abort_slave=1; if (opt_slave_parallel_threads > 0 &&
mi->rli.abort_slave && mi->rli.stop_for_until)
{
mi->rli.stop_for_until= false;
mi->rli.parallel.stop_during_until();
}
else
mi->rli.abort_slave=1;
if ((error=terminate_slave_thread(mi->rli.sql_driver_thd, sql_lock, if ((error=terminate_slave_thread(mi->rli.sql_driver_thd, sql_lock,
&mi->rli.stop_cond, &mi->rli.stop_cond,
&mi->rli.slave_running, &mi->rli.slave_running,
@@ -3427,6 +3434,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
message about error in query execution to be printed. message about error in query execution to be printed.
*/ */
rli->abort_slave= 1; rli->abort_slave= 1;
rli->stop_for_until= true;
mysql_mutex_unlock(&rli->data_lock); mysql_mutex_unlock(&rli->data_lock);
delete ev; delete ev;
DBUG_RETURN(1); DBUG_RETURN(1);
@@ -3454,13 +3462,17 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli,
update_state_of_relay_log(rli, ev); update_state_of_relay_log(rli, ev);
/* if (opt_slave_parallel_threads > 0)
Execute queries in parallel, except if slave_skip_counter is set, {
as it's is easier to skip queries in single threaded mode. int res= rli->parallel.do_event(serial_rgi, ev, event_size);
*/ if (res >= 0)
DBUG_RETURN(res);
if (opt_slave_parallel_threads > 0 && rli->slave_skip_counter == 0) /*
DBUG_RETURN(rli->parallel.do_event(serial_rgi, ev, event_size)); Else we proceed to execute the event non-parallel.
This is the case for pre-10.0 events without GTID, and for handling
slave_skip_counter.
*/
}
/* /*
For GTID, allocate a new sub_id for the given domain_id. For GTID, allocate a new sub_id for the given domain_id.
@@ -4371,6 +4383,7 @@ pthread_handler_t handle_slave_sql(void *arg)
Seconds_Behind_Master grows. No big deal. Seconds_Behind_Master grows. No big deal.
*/ */
rli->abort_slave = 0; rli->abort_slave = 0;
rli->stop_for_until= false;
mysql_mutex_unlock(&rli->run_lock); mysql_mutex_unlock(&rli->run_lock);
mysql_cond_broadcast(&rli->start_cond); mysql_cond_broadcast(&rli->start_cond);
@@ -4542,7 +4555,7 @@ log '%s' at position %s, relay log '%s' position: %s%s", RPL_LOG_NAME,
} }
if (opt_slave_parallel_threads > 0) if (opt_slave_parallel_threads > 0)
rli->parallel.wait_for_done(thd); rli->parallel.wait_for_done(thd, rli);
/* Thread stopped. Print the current replication position to the log */ /* Thread stopped. Print the current replication position to the log */
{ {
@@ -4568,7 +4581,7 @@ log '%s' at position %s, relay log '%s' position: %s%s", RPL_LOG_NAME,
get the correct position printed.) get the correct position printed.)
*/ */
if (opt_slave_parallel_threads > 0) if (opt_slave_parallel_threads > 0)
rli->parallel.wait_for_done(thd); rli->parallel.wait_for_done(thd, rli);
/* /*
Some events set some playgrounds, which won't be cleared because thread Some events set some playgrounds, which won't be cleared because thread

View File

@@ -5894,9 +5894,6 @@ static bool fill_alter_inplace_info(THD *thd,
if (new_field) if (new_field)
{ {
ha_alter_info->create_info->fields_option_struct[f_ptr - table->field]=
new_field->option_struct;
/* Field is not dropped. Evaluate changes bitmap for it. */ /* Field is not dropped. Evaluate changes bitmap for it. */
/* /*
@@ -6008,6 +6005,15 @@ static bool fill_alter_inplace_info(THD *thd,
if (new_field->column_format() != field->column_format()) if (new_field->column_format() != field->column_format())
ha_alter_info->handler_flags|= ha_alter_info->handler_flags|=
Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT; Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT;
if (engine_options_differ(field->option_struct, new_field->option_struct,
table->file->ht->field_options))
{
ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_OPTION;
ha_alter_info->create_info->fields_option_struct[f_ptr - table->field]=
new_field->option_struct;
}
} }
else else
{ {

View File

@@ -15192,6 +15192,11 @@ current_role:
grant_role: grant_role:
ident_or_text ident_or_text
{ {
if ($1.length == 0)
{
my_error(ER_INVALID_ROLE, MYF(0), "");
MYSQL_YYABORT;
}
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT; MYSQL_YYABORT;
$$->user = $1; $$->user = $1;

View File

@@ -906,84 +906,84 @@ int ha_example::create(const char *name, TABLE *table_arg,
/** /**
check_if_incompatible_data() called if ALTER TABLE can't detect otherwise check_if_supported_inplace_alter() is used to ask the engine whether
if new and old definition are compatible it can execute this ALTER TABLE statement in place or the server needs to
create a new table and copy th data over.
@details If there are no other explicit signs like changed number of The engine may answer that the inplace alter is not supported or,
fields this function will be called by compare_tables() if supported, whether the server should protect the table from concurrent
(sql/sql_tables.cc) to decide should we rewrite whole table or only .frm accesses. Return values are
file.
HA_ALTER_INPLACE_NOT_SUPPORTED
HA_ALTER_INPLACE_EXCLUSIVE_LOCK
HA_ALTER_INPLACE_SHARED_LOCK
etc
*/ */
bool ha_example::check_if_incompatible_data(HA_CREATE_INFO *info, enum_alter_inplace_result
uint table_changes) ha_example::check_if_supported_inplace_alter(TABLE* altered_table,
Alter_inplace_info* ha_alter_info)
{ {
ha_table_option_struct *param_old, *param_new; HA_CREATE_INFO *info= ha_alter_info->create_info;
DBUG_ENTER("ha_example::check_if_incompatible_data"); DBUG_ENTER("ha_example::check_if_supported_inplace_alter");
/*
This example shows how custom engine specific table and field
options can be accessed from this function to be compared.
*/
param_new= info->option_struct;
DBUG_PRINT("info", ("new strparam: '%-.64s' ullparam: %llu enumparam: %u "
"boolparam: %u",
(param_new->strparam ? param_new->strparam : "<NULL>"),
param_new->ullparam, param_new->enumparam,
param_new->boolparam));
param_old= table->s->option_struct; if (ha_alter_info->handler_flags & Alter_inplace_info::CHANGE_CREATE_OPTION)
DBUG_PRINT("info", ("old strparam: '%-.64s' ullparam: %llu enumparam: %u "
"boolparam: %u",
(param_old->strparam ? param_old->strparam : "<NULL>"),
param_old->ullparam, param_old->enumparam,
param_old->boolparam));
/*
check important parameters:
for this example engine, we'll assume that changing ullparam or
boolparam requires a table to be rebuilt, while changing strparam
or enumparam - does not.
For debugging purposes we'll announce this to the user
(don't do it in production!)
*/
if (param_new->ullparam != param_old->ullparam)
{ {
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE, /*
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: ULL %llu -> %llu", This example shows how custom engine specific table and field
param_old->ullparam, param_new->ullparam); options can be accessed from this function to be compared.
DBUG_RETURN(COMPATIBLE_DATA_NO); */
} ha_table_option_struct *param_new= info->option_struct;
ha_table_option_struct *param_old= table->s->option_struct;
if (param_new->boolparam != param_old->boolparam) /*
{ check important parameters:
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE, for this example engine, we'll assume that changing ullparam or
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: YESNO %u -> %u", boolparam requires a table to be rebuilt, while changing strparam
param_old->boolparam, param_new->boolparam); or enumparam - does not.
DBUG_RETURN(COMPATIBLE_DATA_NO);
}
for (uint i= 0; i < table->s->fields; i++) For debugging purposes we'll announce this to the user
{ (don't do it in production!)
ha_field_option_struct *f_old, *f_new;
f_old= table->s->field[i]->option_struct; */
DBUG_ASSERT(f_old); if (param_new->ullparam != param_old->ullparam)
if (info->fields_option_struct[i])
{ {
f_new= info->fields_option_struct[i];
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE, push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: Field %`s COMPLEX '%s' -> '%s'", ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: ULL %llu -> %llu",
table->s->field[i]->field_name, param_old->ullparam, param_new->ullparam);
f_old->complex_param_to_parse_it_in_engine, DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
f_new->complex_param_to_parse_it_in_engine); }
if (param_new->boolparam != param_old->boolparam)
{
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: YESNO %u -> %u",
param_old->boolparam, param_new->boolparam);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
} }
else
DBUG_PRINT("info", ("old field %i did not changed", i));
} }
DBUG_RETURN(COMPATIBLE_DATA_YES); if (ha_alter_info->handler_flags & Alter_inplace_info::ALTER_COLUMN_OPTION)
{
for (uint i= 0; i < table->s->fields; i++)
{
ha_field_option_struct *f_old= table->s->field[i]->option_struct;
ha_field_option_struct *f_new= info->fields_option_struct[i];
DBUG_ASSERT(f_old);
if (f_new)
{
push_warning_printf(ha_thd(), Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "EXAMPLE DEBUG: Field %`s COMPLEX '%s' -> '%s'",
table->s->field[i]->field_name,
f_old->complex_param_to_parse_it_in_engine,
f_new->complex_param_to_parse_it_in_engine);
}
else
DBUG_PRINT("info", ("old field %i did not changed", i));
}
}
DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
} }

View File

@@ -247,8 +247,9 @@ public:
int delete_table(const char *from); int delete_table(const char *from);
int create(const char *name, TABLE *form, int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); ///< required HA_CREATE_INFO *create_info); ///< required
bool check_if_incompatible_data(HA_CREATE_INFO *info, enum_alter_inplace_result
uint table_changes); check_if_supported_inplace_alter(TABLE* altered_table,
Alter_inplace_info* ha_alter_info);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); ///< required enum thr_lock_type lock_type); ///< required

View File

@@ -44,7 +44,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6 #define INNODB_VERSION_MINOR 6
#define INNODB_VERSION_BUGFIX 14 #define INNODB_VERSION_BUGFIX 15
/* The following is the InnoDB version as shown in /* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins; SELECT plugin_version FROM information_schema.plugins;

View File

@@ -538,7 +538,11 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
origid= destid= weight= 0; origid= destid= weight= 0;
// Here we're abusing init_tmp_table_share() which is normally only works for thread-local shares.
init_tmp_table_share( thd, share, table->s->db.str, table->s->db.length, options->table_name, ""); init_tmp_table_share( thd, share, table->s->db.str, table->s->db.length, options->table_name, "");
// because of that, we need to reinitialize the memroot (to reset MY_THREAD_SPECIFIC flag)
DBUG_ASSERT(share->mem_root.used == NULL); // it's still empty
init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0));
// What I think this code is doing: // What I think this code is doing:
// * Our OQGRAPH table is `database_blah/name` // * Our OQGRAPH table is `database_blah/name`

View File

@@ -0,0 +1,32 @@
CREATE TABLE oq_backing (
origid INT UNSIGNED NOT NULL,
destid INT UNSIGNED NOT NULL,
weight DOUBLE NOT NULL,
PRIMARY KEY (origid, destid),
KEY (destid)
);
CREATE TABLE oq_table (
latch VARCHAR(32) NULL,
origid BIGINT UNSIGNED NULL,
destid BIGINT UNSIGNED NULL,
weight DOUBLE NULL,
seq BIGINT UNSIGNED NULL,
linkid BIGINT UNSIGNED NULL,
KEY (latch, origid, destid) USING HASH,
KEY (latch, destid, origid) USING HASH
) ENGINE=OQGRAPH
data_table='oq_backing' origid='origid' destid='destid' weight='weight';
flush tables;
show fields in oq_table;
Field Type Null Key Default Extra
latch varchar(32) YES MUL NULL
origid bigint(20) unsigned YES NULL
destid bigint(20) unsigned YES NULL
weight double YES NULL
seq bigint(20) unsigned YES NULL
linkid bigint(20) unsigned YES NULL
show tables;
Tables_in_test
oq_backing
oq_table
drop table oq_table, oq_backing;

View File

@@ -0,0 +1,37 @@
#
# MDEV-5748 Assertion `status_var.memory_used == 0' fails on disconnect after opening an OQGRAPH table
#
# try to open oqgraph table in one connection and use in another:
--connect (con1,localhost,root,,)
CREATE TABLE oq_backing (
origid INT UNSIGNED NOT NULL,
destid INT UNSIGNED NOT NULL,
weight DOUBLE NOT NULL,
PRIMARY KEY (origid, destid),
KEY (destid)
);
CREATE TABLE oq_table (
latch VARCHAR(32) NULL,
origid BIGINT UNSIGNED NULL,
destid BIGINT UNSIGNED NULL,
weight DOUBLE NULL,
seq BIGINT UNSIGNED NULL,
linkid BIGINT UNSIGNED NULL,
KEY (latch, origid, destid) USING HASH,
KEY (latch, destid, origid) USING HASH
) ENGINE=OQGRAPH
data_table='oq_backing' origid='origid' destid='destid' weight='weight';
flush tables;
show fields in oq_table;
--disconnect con1
--connection default
show tables;
drop table oq_table, oq_backing;

View File

@@ -16,8 +16,7 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/sql
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${CMAKE_SOURCE_DIR}/extra/yassl/include) ${CMAKE_SOURCE_DIR}/extra/yassl/include)
ADD_DEFINITIONS(-DMYSQL_SERVER) ADD_DEFINITIONS(-DMYSQL_SERVER)

View File

@@ -15,8 +15,7 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/include/mysql ${CMAKE_SOURCE_DIR}/include/mysql
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/sql
${SSL_INCLUDE_DIRS} ${SSL_INCLUDE_DIRS}
${CMAKE_SOURCE_DIR}/unittest/mytap ${CMAKE_SOURCE_DIR}/unittest/mytap

View File

@@ -40,6 +40,10 @@ show create table se;
ERROR 42S02: Table 'test.se' doesn't exist ERROR 42S02: Table 'test.se' doesn't exist
show create table seq_1_to_15_step_0; show create table seq_1_to_15_step_0;
ERROR HY000: Got error 140 "Wrong create options" from storage engine SEQUENCE ERROR HY000: Got error 140 "Wrong create options" from storage engine SEQUENCE
show create table `seq_-1_to_15`;
ERROR 42S02: Table 'test.seq_-1_to_15' doesn't exist
show create table `seq_1_to_+2`;
ERROR 42S02: Table 'test.seq_1_to_+2' doesn't exist
select * from seq_1_to_15_step_2; select * from seq_1_to_15_step_2;
seq seq
1 1

View File

@@ -26,6 +26,14 @@ show create table se;
--error ER_GET_ERRNO --error ER_GET_ERRNO
show create table seq_1_to_15_step_0; show create table seq_1_to_15_step_0;
#
# MDEV-5735 Selecting from SEQUENCE table with negative number hangs server
#
--error ER_NO_SUCH_TABLE
show create table `seq_-1_to_15`;
--error ER_NO_SUCH_TABLE
show create table `seq_1_to_+2`;
# simple select # simple select
select * from seq_1_to_15_step_2; select * from seq_1_to_15_step_2;
select * from seq_1_to_15; select * from seq_1_to_15;

View File

@@ -20,6 +20,7 @@
a engine that auto-creates tables with rows filled with sequential values a engine that auto-creates tables with rows filled with sequential values
*/ */
#include <ctype.h>
#include <mysql_version.h> #include <mysql_version.h>
#include <handler.h> #include <handler.h>
#include <table.h> #include <table.h>
@@ -265,14 +266,19 @@ static handler *create_handler(handlerton *hton, TABLE_SHARE *table,
static bool parse_table_name(const char *name, size_t name_length, static bool parse_table_name(const char *name, size_t name_length,
ulonglong *from, ulonglong *to, ulonglong *step) ulonglong *from, ulonglong *to, ulonglong *step)
{ {
uint n1= 0, n2= 0; uint n0=0, n1= 0, n2= 0;
*step= 1; *step= 1;
// the table is discovered if its name matches the pattern of seq_1_to_10 or // the table is discovered if its name matches the pattern of seq_1_to_10 or
// seq_1_to_10_step_3 // seq_1_to_10_step_3
sscanf(name, "seq_%llu_to_%llu%n_step_%llu%n", sscanf(name, "seq_%llu_to_%n%llu%n_step_%llu%n",
from, to, &n1, step, &n2); from, &n0, to, &n1, step, &n2);
return n1 != name_length && n2 != name_length; // I consider this a bug in sscanf() - when an unsigned number
// is requested, -5 should *not* be accepted. But is is :(
// hence the additional check below:
return
n0 == 0 || !isdigit(name[4]) || !isdigit(name[n0]) || // reject negative numbers
(n1 != name_length && n2 != name_length);
} }

View File

@@ -276,18 +276,17 @@ void my_hash_sort_8bit_bin(CHARSET_INFO *cs __attribute__((unused)),
const uchar *key, size_t len, const uchar *key, size_t len,
ulong *nr1, ulong *nr2) ulong *nr1, ulong *nr2)
{ {
const uchar *pos = key;
/* /*
Remove trailing spaces. We have to do this to be able to compare Remove trailing spaces. We have to do this to be able to compare
'A ' and 'A' as identical 'A ' and 'A' as identical
*/ */
key= skip_trailing_space(key, len); const uchar *end = skip_trailing_space(key, len);
for (; pos < (uchar*) key ; pos++) for (; key < end ; key++)
{ {
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
((uint)*pos)) + (nr1[0] << 8); ((uint)*key)) + (nr1[0] << 8);
nr2[0]+=3; nr2[0]+=3;
} }
} }
@@ -296,14 +295,12 @@ void my_hash_sort_8bit_bin(CHARSET_INFO *cs __attribute__((unused)),
void my_hash_sort_bin(CHARSET_INFO *cs __attribute__((unused)), void my_hash_sort_bin(CHARSET_INFO *cs __attribute__((unused)),
const uchar *key, size_t len,ulong *nr1, ulong *nr2) const uchar *key, size_t len,ulong *nr1, ulong *nr2)
{ {
const uchar *pos = key; const uchar *end = key + len;
key+= len; for (; key < end ; key++)
for (; pos < (uchar*) key ; pos++)
{ {
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
((uint)*pos)) + (nr1[0] << 8); ((uint)*key)) + (nr1[0] << 8);
nr2[0]+=3; nr2[0]+=3;
} }
} }

View File

@@ -680,18 +680,16 @@ void
my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)), my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
const uchar *key, size_t len,ulong *nr1, ulong *nr2) const uchar *key, size_t len,ulong *nr1, ulong *nr2)
{ {
const uchar *pos = key;
/* /*
Remove trailing spaces. We have to do this to be able to compare Remove trailing spaces. We have to do this to be able to compare
'A ' and 'A' as identical 'A ' and 'A' as identical
*/ */
key= skip_trailing_space(key, len); const uchar *end = skip_trailing_space(key, len);
for (; pos < (uchar*) key ; pos++) for (; key < end ; key++)
{ {
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
((uint)*pos)) + (nr1[0] << 8); ((uint)*key)) + (nr1[0] << 8);
nr2[0]+=3; nr2[0]+=3;
} }
} }

View File

@@ -3311,17 +3311,15 @@ static
void my_hash_sort_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)), void my_hash_sort_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)),
const uchar *key, size_t len,ulong *nr1, ulong *nr2) const uchar *key, size_t len,ulong *nr1, ulong *nr2)
{ {
const uchar *pos = key; const uchar *end = key + len;
key+= len;
while (key > pos+1 && key[-1] == ' ' && key[-2] == '\0') while (end > key+1 && end[-1] == ' ' && end[-2] == '\0')
key-= 2; end-= 2;
for (; pos < (uchar*) key ; pos++) for (; key < (uchar*) end ; key++)
{ {
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
((uint)*pos)) + (nr1[0] << 8); ((uint)*key)) + (nr1[0] << 8);
nr2[0]+=3; nr2[0]+=3;
} }
} }

View File

@@ -14,8 +14,7 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql
${CMAKE_BINARY_DIR}/pcre ${PCRE_INCLUDES}
${CMAKE_SOURCE_DIR}/pcre
${CMAKE_SOURCE_DIR}/extra/yassl/include) ${CMAKE_SOURCE_DIR}/extra/yassl/include)
MY_ADD_TESTS(bitmap base64 my_vsnprintf my_atomic my_rdtsc lf my_malloc MY_ADD_TESTS(bitmap base64 my_vsnprintf my_atomic my_rdtsc lf my_malloc