Merge 10.2 into 10.3

This commit is contained in:
Marko Mäkelä 2019-06-19 08:56:10 +03:00
commit 192aa295b4
41 changed files with 668 additions and 399 deletions

View file

@ -1,6 +1,6 @@
/* /*
Copyright (c) 2000, 2018, Oracle and/or its affiliates. Copyright (c) 2000, 2018, Oracle and/or its affiliates.
Copyright (c) 2009, 2018, MariaDB Corporation Copyright (c) 2009, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -40,6 +40,7 @@
#include "my_readline.h" #include "my_readline.h"
#include <signal.h> #include <signal.h>
#include <violite.h> #include <violite.h>
#include <my_sys.h>
#include <source_revision.h> #include <source_revision.h>
#if defined(USE_LIBEDIT_INTERFACE) && defined(HAVE_LOCALE_H) #if defined(USE_LIBEDIT_INTERFACE) && defined(HAVE_LOCALE_H)
#include <locale.h> #include <locale.h>
@ -4697,7 +4698,8 @@ sql_real_connect(char *host,char *database,char *user,char *password,
select_limit,max_join_size); select_limit,max_join_size);
mysql_options(&mysql, MYSQL_INIT_COMMAND, init_command); mysql_options(&mysql, MYSQL_INIT_COMMAND, init_command);
} }
if (!strcmp(default_charset,MYSQL_AUTODETECT_CHARSET_NAME))
default_charset= (char *)my_default_csname();
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
if (!do_connect(&mysql, host, user, password, database, if (!do_connect(&mysql, host, user, password, database,

View file

@ -26,6 +26,7 @@
#include <welcome_copyright_notice.h> #include <welcome_copyright_notice.h>
#include <my_rnd.h> #include <my_rnd.h>
#include <password.h> #include <password.h>
#include <my_sys.h>
#define ADMIN_VERSION "9.1" #define ADMIN_VERSION "9.1"
#define MAX_MYSQL_VAR 512 #define MAX_MYSQL_VAR 512
@ -371,6 +372,8 @@ int main(int argc,char *argv[])
if (shared_memory_base_name) if (shared_memory_base_name)
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif #endif
if (!strcmp(default_charset,MYSQL_AUTODETECT_CHARSET_NAME))
default_charset= (char *)my_default_csname();
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
error_flags= (myf)(opt_nobeep ? 0 : ME_BELL); error_flags= (myf)(opt_nobeep ? 0 : ME_BELL);

View file

@ -440,8 +440,10 @@ static int get_options(int *argc, char ***argv)
else else
default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME; default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME;
} }
if (strcmp(default_charset, MYSQL_AUTODETECT_CHARSET_NAME) && if (!strcmp(default_charset, MYSQL_AUTODETECT_CHARSET_NAME))
!get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME))) default_charset= (char *)my_default_csname();
if (!get_charset_by_csname(default_charset, MY_CS_PRIMARY, MYF(MY_WME)))
{ {
printf("Unsupported character set: %s\n", default_charset); printf("Unsupported character set: %s\n", default_charset);
DBUG_RETURN(1); DBUG_RETURN(1);

View file

@ -30,6 +30,8 @@
#define IMPORT_VERSION "3.7" #define IMPORT_VERSION "3.7"
#include "client_priv.h" #include "client_priv.h"
#include <my_sys.h>
#include "mysql_version.h" #include "mysql_version.h"
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */ #include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
@ -472,8 +474,9 @@ static MYSQL *db_connect(char *host, char *database,
if (opt_default_auth && *opt_default_auth) if (opt_default_auth && *opt_default_auth)
mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth); mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
if (!strcmp(default_charset,MYSQL_AUTODETECT_CHARSET_NAME))
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset); default_charset= (char *)my_default_csname();
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, my_default_csname());
mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
"program_name", "mysqlimport"); "program_name", "mysqlimport");

View file

@ -135,6 +135,8 @@ int main(int argc, char **argv)
if (shared_memory_base_name) if (shared_memory_base_name)
mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name); mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif #endif
if (!strcmp(default_charset,MYSQL_AUTODETECT_CHARSET_NAME))
default_charset= (char *)my_default_csname();
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
if (opt_plugin_dir && *opt_plugin_dir) if (opt_plugin_dir && *opt_plugin_dir)

View file

@ -1049,6 +1049,7 @@ extern char *get_tty_password(const char *opt_message);
/* File system character set */ /* File system character set */
extern CHARSET_INFO *fs_character_set(void); extern CHARSET_INFO *fs_character_set(void);
#endif #endif
extern const char *my_default_csname(void);
extern size_t escape_quotes_for_mysql(CHARSET_INFO *charset_info, extern size_t escape_quotes_for_mysql(CHARSET_INFO *charset_info,
char *to, size_t to_length, char *to, size_t to_length,
const char *from, size_t length); const char *from, size_t length);

View file

@ -0,0 +1,2 @@
@@character_set_client
cp1257

View file

@ -0,0 +1,2 @@
--source include/windows.inc
--exec chcp 1257 > NUL && $MYSQL --default-character-set=auto -e "select @@character_set_client"

View file

@ -47,3 +47,46 @@ t1 CREATE TABLE `t1` (
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 TRANSACTIONAL=1 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 TRANSACTIONAL=1
CREATE TABLE t2 SELECT * FROM t1; CREATE TABLE t2 SELECT * FROM t1;
DROP TABLE t1, t2; DROP TABLE t1, t2;
#
# MDEV-19055 Assertion `(_my_thread_var())->thr_errno != 0' failed in pagecache_read
#
CREATE OR REPLACE TABLE t1 (x INT) ENGINE=Aria;
CREATE TEMPORARY TABLE t2 (a TIME) ENGINE=Aria;
ALTER TABLE t2 ADD b DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE t2 ADD CHECK (b = 4);
INSERT IGNORE INTO t2 () VALUES (),(),(),();
ALTER IGNORE TABLE t2 ADD c INT;
SELECT count(a),sum(a) FROM t2;
count(a) sum(a)
0 NULL
DELETE FROM t2 ORDER BY c LIMIT 1;
INSERT IGNORE INTO t2 SELECT * FROM t2;
OPTIMIZE TABLE t2;
Table Op Msg_type Msg_text
test.t2 optimize status OK
SELECT count(a),sum(a) FROM t2;
count(a) sum(a)
0 NULL
INSERT IGNORE INTO t2 SELECT * FROM t2;
SET SQL_MODE= 'STRICT_ALL_TABLES';
SELECT count(a),sum(a) FROM t2;
count(a) sum(a)
0 NULL
ALTER TABLE t2 CHANGE IF EXISTS d c INT;
ERROR 22007: Incorrect datetime value: '4'
SELECT count(a),sum(a) FROM t2;
count(a) sum(a)
0 NULL
ALTER IGNORE TABLE t2 ADD IF NOT EXISTS e BIT;
ALTER TABLE t1 MODIFY IF EXISTS xx INT;
INSERT IGNORE INTO t2 () VALUES (),(),(),();
SELECT count(a),sum(a) FROM t2;
count(a) sum(a)
0 NULL
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
check table t2;
Table Op Msg_type Msg_text
test.t2 check status OK
DROP TABLE t1,t2;

View file

@ -42,3 +42,38 @@ ALTER TABLE t1 ORDER BY unknown_column;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
CREATE TABLE t2 SELECT * FROM t1; CREATE TABLE t2 SELECT * FROM t1;
DROP TABLE t1, t2; DROP TABLE t1, t2;
--echo #
--echo # MDEV-19055 Assertion `(_my_thread_var())->thr_errno != 0' failed in pagecache_read
--echo #
--disable_warnings
CREATE OR REPLACE TABLE t1 (x INT) ENGINE=Aria;
CREATE TEMPORARY TABLE t2 (a TIME) ENGINE=Aria;
ALTER TABLE t2 ADD b DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE t2 ADD CHECK (b = 4);
INSERT IGNORE INTO t2 () VALUES (),(),(),();
ALTER IGNORE TABLE t2 ADD c INT;
SELECT count(a),sum(a) FROM t2;
DELETE FROM t2 ORDER BY c LIMIT 1;
INSERT IGNORE INTO t2 SELECT * FROM t2;
OPTIMIZE TABLE t2;
SELECT count(a),sum(a) FROM t2;
INSERT IGNORE INTO t2 SELECT * FROM t2;
SET SQL_MODE= 'STRICT_ALL_TABLES';
SELECT count(a),sum(a) FROM t2;
--error ER_TRUNCATED_WRONG_VALUE
ALTER TABLE t2 CHANGE IF EXISTS d c INT;
SELECT count(a),sum(a) FROM t2;
ALTER IGNORE TABLE t2 ADD IF NOT EXISTS e BIT;
ALTER TABLE t1 MODIFY IF EXISTS xx INT;
INSERT IGNORE INTO t2 () VALUES (),(),(),();
SELECT count(a),sum(a) FROM t2;
--enable_warnings
check table t1;
check table t2;
DROP TABLE t1,t2;
#
# End of 10.2 tests
#

View file

@ -0,0 +1,23 @@
CREATE TABLE t1 (b INT);
INSERT INTO t1 VALUES (5);
CREATE TEMPORARY TABLE t1 (a INT) ENGINE=Aria ROW_FORMAT=DYNAMIC;
INSERT INTO t1 VALUES (1);
DELETE FROM t1 LIMIT 2;
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT * FROM t1;
a
INSERT INTO t1 VALUES (1),(2);
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
ALTER TABLE t1 CHANGE COLUMN IF EXISTS x x INT;
Warnings:
Note 1054 Unknown column 'x' in 't1'
ALTER TABLE t1;
DROP TEMPORARY TABLE t1;
DROP TABLE t1;

View file

@ -0,0 +1,20 @@
#
# MDEV-19595
# ER_CRASHED_ON_USAGE and Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())'
# failed upon actions on temporary Aria table with ROW_FORMAT DYNAMIC
#
CREATE TABLE t1 (b INT);
INSERT INTO t1 VALUES (5);
CREATE TEMPORARY TABLE t1 (a INT) ENGINE=Aria ROW_FORMAT=DYNAMIC;
INSERT INTO t1 VALUES (1);
DELETE FROM t1 LIMIT 2;
OPTIMIZE TABLE t1;
CHECK TABLE t1;
SELECT * FROM t1;
INSERT INTO t1 VALUES (1),(2);
CHECK TABLE t1;
ALTER TABLE t1 CHANGE COLUMN IF EXISTS x x INT;
ALTER TABLE t1;
DROP TEMPORARY TABLE t1;
DROP TABLE t1;

View file

@ -203,10 +203,10 @@ drop table t1;
create table t1 (a int, b int); create table t1 (a int, b int);
insert into t1 values (3, 30), (4, 20), (1, 20); insert into t1 values (3, 30), (4, 20), (1, 20);
create table t2 (c int, d int, v int as (d+1), index idx(c)); create table t2 (c int, d int, v int as (d+1), index idx(c));
insert into t2(c,d) values insert into t2(c,d) values
(20, 100), (20, 300), (30, 100), (30, 200), (40, 500), (20, 100), (20, 300), (30, 100), (30, 200), (40, 500),
(70, 100), (40, 300), (60, 100), (40, 100), (70, 100); (70, 100), (40, 300), (60, 100), (40, 100), (70, 100);
insert into t2(c,d) values insert into t2(c,d) values
(120, 100), (150, 300), (130, 100), (130, 200), (140, 500), (120, 100), (150, 300), (130, 100), (130, 200), (140, 500),
(170, 100), (180, 300), (160, 100), (40, 100), (170, 100); (170, 100), (180, 300), (160, 100), (40, 100), (170, 100);
set join_cache_level=6; set join_cache_level=6;
@ -423,5 +423,43 @@ ERROR HY000: Incorrect information in file: './test/t1.frm'
ALTER TABLE t1; ALTER TABLE t1;
ERROR HY000: Incorrect information in file: './test/t1.frm' ERROR HY000: Incorrect information in file: './test/t1.frm'
# #
# MDEV-19771 REPLACE on table with virtual_field can cause crash in set_ok_status()
create or replace table t1 (pk int primary key, col_bit bit(15) default null,
vcol_bit bit(10) GENERATED ALWAYS AS (`col_bit`) VIRTUAL);
replace INTO `t1` (`pk`,col_bit) VALUES (99,1000);
select pk, col_bit+0, vcol_bit+0 from t1;
pk col_bit+0 vcol_bit+0
99 1000 1000
replace INTO `t1` (`pk`,col_bit) VALUES (99,10000);
select pk, col_bit+0, vcol_bit+0 from t1;
pk col_bit+0 vcol_bit+0
99 10000 1023
REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99);
Warnings:
Warning 1264 Out of range value for column 'vcol_bit' at row 1
drop table t1;
#
# MDEV-17837 REPLACE on table with virtual_field can cause crash in set_ok_status()
#
SET @old_sql_mode=@@sql_mode;
SET sql_mode= STRICT_ALL_TABLES;
CREATE TABLE t1 (
pk INT,
i TINYINT,
vi TINYINT AS (i+1) PERSISTENT,
PRIMARY KEY(pk)
);
INSERT INTO t1 (pk,i) VALUES (1,1);
TRUNCATE TABLE t1;
INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
Warnings:
Warning 1264 Out of range value for column 'vi' at row 1
REPLACE INTO t1 (pk,i) VALUES (1,2);
Warnings:
Warning 1264 Out of range value for column 'vi' at row 1
DROP TABLE t1;
SET @sql_mode=@old_sql_mode;
#
# End of 10.2 tests # End of 10.2 tests
# #

View file

@ -215,12 +215,12 @@ drop table t1;
create table t1 (a int, b int); create table t1 (a int, b int);
insert into t1 values (3, 30), (4, 20), (1, 20); insert into t1 values (3, 30), (4, 20), (1, 20);
create table t2 (c int, d int, v int as (d+1), index idx(c)); create table t2 (c int, d int, v int as (d+1), index idx(c));
insert into t2(c,d) values insert into t2(c,d) values
(20, 100), (20, 300), (30, 100), (30, 200), (40, 500), (20, 100), (20, 300), (30, 100), (30, 200), (40, 500),
(70, 100), (40, 300), (60, 100), (40, 100), (70, 100); (70, 100), (40, 300), (60, 100), (40, 100), (70, 100);
insert into t2(c,d) values insert into t2(c,d) values
(120, 100), (150, 300), (130, 100), (130, 200), (140, 500), (120, 100), (150, 300), (130, 100), (130, 200), (140, 500),
(170, 100), (180, 300), (160, 100), (40, 100), (170, 100); (170, 100), (180, 300), (160, 100), (40, 100), (170, 100);
set join_cache_level=6; set join_cache_level=6;
explain explain
@ -391,6 +391,40 @@ SHOW CREATE TABLE t1;
ALTER TABLE t1; ALTER TABLE t1;
--remove_file $MYSQLD_DATADIR/test/t1.frm --remove_file $MYSQLD_DATADIR/test/t1.frm
--echo #
--echo # MDEV-19771 REPLACE on table with virtual_field can cause crash in set_ok_status()
--echo
create or replace table t1 (pk int primary key, col_bit bit(15) default null,
vcol_bit bit(10) GENERATED ALWAYS AS (`col_bit`) VIRTUAL);
replace INTO `t1` (`pk`,col_bit) VALUES (99,1000);
select pk, col_bit+0, vcol_bit+0 from t1;
replace INTO `t1` (`pk`,col_bit) VALUES (99,10000);
select pk, col_bit+0, vcol_bit+0 from t1;
REPLACE LOW_PRIORITY INTO `t1` (`pk`) VALUES (99);
drop table t1;
--echo #
--echo # MDEV-17837 REPLACE on table with virtual_field can cause crash in set_ok_status()
--echo #
SET @old_sql_mode=@@sql_mode;
SET sql_mode= STRICT_ALL_TABLES;
CREATE TABLE t1 (
pk INT,
i TINYINT,
vi TINYINT AS (i+1) PERSISTENT,
PRIMARY KEY(pk)
);
INSERT INTO t1 (pk,i) VALUES (1,1);
TRUNCATE TABLE t1;
INSERT IGNORE INTO t1 (pk,i) VALUES (1,127);
REPLACE INTO t1 (pk,i) VALUES (1,2);
DROP TABLE t1;
SET @sql_mode=@old_sql_mode;
--echo # --echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #

View file

@ -20,7 +20,12 @@
#include <m_string.h> #include <m_string.h>
#include <my_dir.h> #include <my_dir.h>
#include <my_xml.h> #include <my_xml.h>
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
/* /*
The code below implements this functionality: The code below implements this functionality:
@ -1216,3 +1221,214 @@ size_t escape_quotes_for_mysql(CHARSET_INFO *charset_info,
*to= 0; *to= 0;
return overflow ? (ulong)~0 : (ulong) (to - to_start); return overflow ? (ulong)~0 : (ulong) (to - to_start);
} }
typedef enum my_cs_match_type_enum
{
/* MySQL and OS charsets are fully compatible */
my_cs_exact,
/* MySQL charset is very close to OS charset */
my_cs_approx,
/*
MySQL knows this charset, but it is not supported as client character set.
*/
my_cs_unsupp
} my_cs_match_type;
typedef struct str2str_st
{
const char* os_name;
const char* my_name;
my_cs_match_type param;
} MY_CSET_OS_NAME;
static const MY_CSET_OS_NAME charsets[] =
{
#ifdef _WIN32
{"cp437", "cp850", my_cs_approx},
{"cp850", "cp850", my_cs_exact},
{"cp852", "cp852", my_cs_exact},
{"cp858", "cp850", my_cs_approx},
{"cp866", "cp866", my_cs_exact},
{"cp874", "tis620", my_cs_approx},
{"cp932", "cp932", my_cs_exact},
{"cp936", "gbk", my_cs_approx},
{"cp949", "euckr", my_cs_approx},
{"cp950", "big5", my_cs_exact},
{"cp1200", "utf16le", my_cs_unsupp},
{"cp1201", "utf16", my_cs_unsupp},
{"cp1250", "cp1250", my_cs_exact},
{"cp1251", "cp1251", my_cs_exact},
{"cp1252", "latin1", my_cs_exact},
{"cp1253", "greek", my_cs_exact},
{"cp1254", "latin5", my_cs_exact},
{"cp1255", "hebrew", my_cs_approx},
{"cp1256", "cp1256", my_cs_exact},
{"cp1257", "cp1257", my_cs_exact},
{"cp10000", "macroman", my_cs_exact},
{"cp10001", "sjis", my_cs_approx},
{"cp10002", "big5", my_cs_approx},
{"cp10008", "gb2312", my_cs_approx},
{"cp10021", "tis620", my_cs_approx},
{"cp10029", "macce", my_cs_exact},
{"cp12001", "utf32", my_cs_unsupp},
{"cp20107", "swe7", my_cs_exact},
{"cp20127", "latin1", my_cs_approx},
{"cp20866", "koi8r", my_cs_exact},
{"cp20932", "ujis", my_cs_exact},
{"cp20936", "gb2312", my_cs_approx},
{"cp20949", "euckr", my_cs_approx},
{"cp21866", "koi8u", my_cs_exact},
{"cp28591", "latin1", my_cs_approx},
{"cp28592", "latin2", my_cs_exact},
{"cp28597", "greek", my_cs_exact},
{"cp28598", "hebrew", my_cs_exact},
{"cp28599", "latin5", my_cs_exact},
{"cp28603", "latin7", my_cs_exact},
#ifdef UNCOMMENT_THIS_WHEN_WL_4579_IS_DONE
{"cp28605", "latin9", my_cs_exact},
#endif
{"cp38598", "hebrew", my_cs_exact},
{"cp51932", "ujis", my_cs_exact},
{"cp51936", "gb2312", my_cs_exact},
{"cp51949", "euckr", my_cs_exact},
{"cp51950", "big5", my_cs_exact},
#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE
{"cp54936", "gb18030", my_cs_exact},
#endif
{"cp65001", "utf8", my_cs_exact},
#else /* not Windows */
{"646", "latin1", my_cs_approx}, /* Default on Solaris */
{"ANSI_X3.4-1968", "latin1", my_cs_approx},
{"ansi1251", "cp1251", my_cs_exact},
{"armscii8", "armscii8", my_cs_exact},
{"armscii-8", "armscii8", my_cs_exact},
{"ASCII", "latin1", my_cs_approx},
{"Big5", "big5", my_cs_exact},
{"cp1251", "cp1251", my_cs_exact},
{"cp1255", "hebrew", my_cs_approx},
{"CP866", "cp866", my_cs_exact},
{"eucCN", "gb2312", my_cs_exact},
{"euc-CN", "gb2312", my_cs_exact},
{"eucJP", "ujis", my_cs_exact},
{"euc-JP", "ujis", my_cs_exact},
{"eucKR", "euckr", my_cs_exact},
{"euc-KR", "euckr", my_cs_exact},
#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE
{"gb18030", "gb18030", my_cs_exact},
#endif
{"gb2312", "gb2312", my_cs_exact},
{"gbk", "gbk", my_cs_exact},
{"georgianps", "geostd8", my_cs_exact},
{"georgian-ps", "geostd8", my_cs_exact},
{"IBM-1252", "cp1252", my_cs_exact},
{"iso88591", "latin1", my_cs_approx},
{"ISO_8859-1", "latin1", my_cs_approx},
{"ISO8859-1", "latin1", my_cs_approx},
{"ISO-8859-1", "latin1", my_cs_approx},
{"iso885913", "latin7", my_cs_exact},
{"ISO_8859-13", "latin7", my_cs_exact},
{"ISO8859-13", "latin7", my_cs_exact},
{"ISO-8859-13", "latin7", my_cs_exact},
#ifdef UNCOMMENT_THIS_WHEN_WL_4579_IS_DONE
{"iso885915", "latin9", my_cs_exact},
{"ISO_8859-15", "latin9", my_cs_exact},
{"ISO8859-15", "latin9", my_cs_exact},
{"ISO-8859-15", "latin9", my_cs_exact},
#endif
{"iso88592", "latin2", my_cs_exact},
{"ISO_8859-2", "latin2", my_cs_exact},
{"ISO8859-2", "latin2", my_cs_exact},
{"ISO-8859-2", "latin2", my_cs_exact},
{"iso88597", "greek", my_cs_exact},
{"ISO_8859-7", "greek", my_cs_exact},
{"ISO8859-7", "greek", my_cs_exact},
{"ISO-8859-7", "greek", my_cs_exact},
{"iso88598", "hebrew", my_cs_exact},
{"ISO_8859-8", "hebrew", my_cs_exact},
{"ISO8859-8", "hebrew", my_cs_exact},
{"ISO-8859-8", "hebrew", my_cs_exact},
{"iso88599", "latin5", my_cs_exact},
{"ISO_8859-9", "latin5", my_cs_exact},
{"ISO8859-9", "latin5", my_cs_exact},
{"ISO-8859-9", "latin5", my_cs_exact},
{"koi8r", "koi8r", my_cs_exact},
{"KOI8-R", "koi8r", my_cs_exact},
{"koi8u", "koi8u", my_cs_exact},
{"KOI8-U", "koi8u", my_cs_exact},
{"roman8", "hp8", my_cs_exact}, /* Default on HP UX */
{"Shift_JIS", "sjis", my_cs_exact},
{"SJIS", "sjis", my_cs_exact},
{"shiftjisx0213", "sjis", my_cs_exact},
{"tis620", "tis620", my_cs_exact},
{"tis-620", "tis620", my_cs_exact},
{"ujis", "ujis", my_cs_exact},
{"US-ASCII", "latin1", my_cs_approx},
{"utf8", "utf8", my_cs_exact},
{"utf-8", "utf8", my_cs_exact},
#endif
{NULL, NULL, 0}
};
static const char*
my_os_charset_to_mysql_charset(const char* csname)
{
const MY_CSET_OS_NAME* csp;
for (csp = charsets; csp->os_name; csp++)
{
if (!strcasecmp(csp->os_name, csname))
{
switch (csp->param)
{
case my_cs_exact:
return csp->my_name;
case my_cs_approx:
/*
Maybe we should print a warning eventually:
character set correspondence is not exact.
*/
return csp->my_name;
default:
return NULL;
}
}
}
return NULL;
}
const char* my_default_csname()
{
const char* csname = NULL;
#ifdef _WIN32
char cpbuf[64];
int cp = GetConsoleCP();
if (cp == 0)
cp = GetACP();
snprintf(cpbuf, sizeof(cpbuf), "cp%d", (int)cp);
csname = my_os_charset_to_mysql_charset(cpbuf);
#elif defined(HAVE_SETLOCALE) && defined(HAVE_NL_LANGINFO)
if (setlocale(LC_CTYPE, "") && (csname = nl_langinfo(CODESET)))
csname = my_os_charset_to_mysql_charset(csname);
#endif
return csname ? csname : MYSQL_DEFAULT_CHARSET_NAME;
}

View file

@ -68,6 +68,8 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
if (readbytes != Count) if (readbytes != Count)
{ {
/* We should never read with wrong file descriptor! */
DBUG_ASSERT(readbytes != (size_t)-1 || errno != EBADF);
my_errno= errno; my_errno= errno;
if (errno == 0 || (readbytes != (size_t) -1 && if (errno == 0 || (readbytes != (size_t) -1 &&
(MyFlags & (MY_NABP | MY_FNABP)))) (MyFlags & (MY_NABP | MY_FNABP))))

View file

@ -1920,250 +1920,13 @@ static MYSQL_METHODS client_methods=
}; };
#include <my_sys.h>
typedef enum my_cs_match_type_enum
{
/* MySQL and OS charsets are fully compatible */
my_cs_exact,
/* MySQL charset is very close to OS charset */
my_cs_approx,
/*
MySQL knows this charset, but it is not supported as client character set.
*/
my_cs_unsupp
} my_cs_match_type;
typedef struct str2str_st
{
const char *os_name;
const char *my_name;
my_cs_match_type param;
} MY_CSET_OS_NAME;
const MY_CSET_OS_NAME charsets[]=
{
#ifdef __WIN__
{"cp437", "cp850", my_cs_approx},
{"cp850", "cp850", my_cs_exact},
{"cp852", "cp852", my_cs_exact},
{"cp858", "cp850", my_cs_approx},
{"cp866", "cp866", my_cs_exact},
{"cp874", "tis620", my_cs_approx},
{"cp932", "cp932", my_cs_exact},
{"cp936", "gbk", my_cs_approx},
{"cp949", "euckr", my_cs_approx},
{"cp950", "big5", my_cs_exact},
{"cp1200", "utf16le", my_cs_unsupp},
{"cp1201", "utf16", my_cs_unsupp},
{"cp1250", "cp1250", my_cs_exact},
{"cp1251", "cp1251", my_cs_exact},
{"cp1252", "latin1", my_cs_exact},
{"cp1253", "greek", my_cs_exact},
{"cp1254", "latin5", my_cs_exact},
{"cp1255", "hebrew", my_cs_approx},
{"cp1256", "cp1256", my_cs_exact},
{"cp1257", "cp1257", my_cs_exact},
{"cp10000", "macroman", my_cs_exact},
{"cp10001", "sjis", my_cs_approx},
{"cp10002", "big5", my_cs_approx},
{"cp10008", "gb2312", my_cs_approx},
{"cp10021", "tis620", my_cs_approx},
{"cp10029", "macce", my_cs_exact},
{"cp12001", "utf32", my_cs_unsupp},
{"cp20107", "swe7", my_cs_exact},
{"cp20127", "latin1", my_cs_approx},
{"cp20866", "koi8r", my_cs_exact},
{"cp20932", "ujis", my_cs_exact},
{"cp20936", "gb2312", my_cs_approx},
{"cp20949", "euckr", my_cs_approx},
{"cp21866", "koi8u", my_cs_exact},
{"cp28591", "latin1", my_cs_approx},
{"cp28592", "latin2", my_cs_exact},
{"cp28597", "greek", my_cs_exact},
{"cp28598", "hebrew", my_cs_exact},
{"cp28599", "latin5", my_cs_exact},
{"cp28603", "latin7", my_cs_exact},
#ifdef UNCOMMENT_THIS_WHEN_WL_4579_IS_DONE
{"cp28605", "latin9", my_cs_exact},
#endif
{"cp38598", "hebrew", my_cs_exact},
{"cp51932", "ujis", my_cs_exact},
{"cp51936", "gb2312", my_cs_exact},
{"cp51949", "euckr", my_cs_exact},
{"cp51950", "big5", my_cs_exact},
#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE
{"cp54936", "gb18030", my_cs_exact},
#endif
{"cp65001", "utf8", my_cs_exact},
#else /* not Windows */
{"646", "latin1", my_cs_approx}, /* Default on Solaris */
{"ANSI_X3.4-1968", "latin1", my_cs_approx},
{"ansi1251", "cp1251", my_cs_exact},
{"armscii8", "armscii8", my_cs_exact},
{"armscii-8", "armscii8", my_cs_exact},
{"ASCII", "latin1", my_cs_approx},
{"Big5", "big5", my_cs_exact},
{"cp1251", "cp1251", my_cs_exact},
{"cp1255", "hebrew", my_cs_approx},
{"CP866", "cp866", my_cs_exact},
{"eucCN", "gb2312", my_cs_exact},
{"euc-CN", "gb2312", my_cs_exact},
{"eucJP", "ujis", my_cs_exact},
{"euc-JP", "ujis", my_cs_exact},
{"eucKR", "euckr", my_cs_exact},
{"euc-KR", "euckr", my_cs_exact},
#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE
{"gb18030", "gb18030", my_cs_exact},
#endif
{"gb2312", "gb2312", my_cs_exact},
{"gbk", "gbk", my_cs_exact},
{"georgianps", "geostd8", my_cs_exact},
{"georgian-ps", "geostd8", my_cs_exact},
{"IBM-1252", "cp1252", my_cs_exact},
{"iso88591", "latin1", my_cs_approx},
{"ISO_8859-1", "latin1", my_cs_approx},
{"ISO8859-1", "latin1", my_cs_approx},
{"ISO-8859-1", "latin1", my_cs_approx},
{"iso885913", "latin7", my_cs_exact},
{"ISO_8859-13", "latin7", my_cs_exact},
{"ISO8859-13", "latin7", my_cs_exact},
{"ISO-8859-13", "latin7", my_cs_exact},
#ifdef UNCOMMENT_THIS_WHEN_WL_4579_IS_DONE
{"iso885915", "latin9", my_cs_exact},
{"ISO_8859-15", "latin9", my_cs_exact},
{"ISO8859-15", "latin9", my_cs_exact},
{"ISO-8859-15", "latin9", my_cs_exact},
#endif
{"iso88592", "latin2", my_cs_exact},
{"ISO_8859-2", "latin2", my_cs_exact},
{"ISO8859-2", "latin2", my_cs_exact},
{"ISO-8859-2", "latin2", my_cs_exact},
{"iso88597", "greek", my_cs_exact},
{"ISO_8859-7", "greek", my_cs_exact},
{"ISO8859-7", "greek", my_cs_exact},
{"ISO-8859-7", "greek", my_cs_exact},
{"iso88598", "hebrew", my_cs_exact},
{"ISO_8859-8", "hebrew", my_cs_exact},
{"ISO8859-8", "hebrew", my_cs_exact},
{"ISO-8859-8", "hebrew", my_cs_exact},
{"iso88599", "latin5", my_cs_exact},
{"ISO_8859-9", "latin5", my_cs_exact},
{"ISO8859-9", "latin5", my_cs_exact},
{"ISO-8859-9", "latin5", my_cs_exact},
{"koi8r", "koi8r", my_cs_exact},
{"KOI8-R", "koi8r", my_cs_exact},
{"koi8u", "koi8u", my_cs_exact},
{"KOI8-U", "koi8u", my_cs_exact},
{"roman8", "hp8", my_cs_exact}, /* Default on HP UX */
{"Shift_JIS", "sjis", my_cs_exact},
{"SJIS", "sjis", my_cs_exact},
{"shiftjisx0213", "sjis", my_cs_exact},
{"tis620", "tis620", my_cs_exact},
{"tis-620", "tis620", my_cs_exact},
{"ujis", "ujis", my_cs_exact},
{"US-ASCII", "latin1", my_cs_approx},
{"utf8", "utf8", my_cs_exact},
{"utf-8", "utf8", my_cs_exact},
#endif
{NULL, NULL, 0}
};
static const char *
my_os_charset_to_mysql_charset(const char *csname)
{
const MY_CSET_OS_NAME *csp;
for (csp= charsets; csp->os_name; csp++)
{
if (!my_strcasecmp(&my_charset_latin1, csp->os_name, csname))
{
switch (csp->param)
{
case my_cs_exact:
return csp->my_name;
case my_cs_approx:
/*
Maybe we should print a warning eventually:
character set correspondence is not exact.
*/
return csp->my_name;
default:
my_printf_error(ER_UNKNOWN_ERROR,
"OS character set '%s'"
" is not supported by MySQL client",
MYF(0), csp->my_name);
goto def;
}
}
}
my_printf_error(ER_UNKNOWN_ERROR,
"Unknown OS character set '%s'.",
MYF(0), csname);
def:
csname= MYSQL_DEFAULT_CHARSET_NAME;
my_printf_error(ER_UNKNOWN_ERROR,
"Switching to the default character set '%s'.",
MYF(0), csname);
return csname;
}
#ifndef __WIN__
#include <stdlib.h> /* for getenv() */
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
#endif /* __WIN__ */
static int static int
mysql_autodetect_character_set(MYSQL *mysql) mysql_autodetect_character_set(MYSQL *mysql)
{ {
const char *csname= MYSQL_DEFAULT_CHARSET_NAME;
#ifdef __WIN__
char cpbuf[64];
{
UINT cp= GetConsoleCP();
if (cp == 0)
cp= GetACP();
my_snprintf(cpbuf, sizeof(cpbuf), "cp%d", (int)cp);
csname= my_os_charset_to_mysql_charset(cpbuf);
}
#elif defined(HAVE_SETLOCALE) && defined(HAVE_NL_LANGINFO)
{
if (setlocale(LC_CTYPE, "") && (csname= nl_langinfo(CODESET)))
csname= my_os_charset_to_mysql_charset(csname);
}
#endif
if (mysql->options.charset_name) if (mysql->options.charset_name)
my_free(mysql->options.charset_name); my_free(mysql->options.charset_name);
if (!(mysql->options.charset_name= my_strdup(csname, MYF(MY_WME)))) if (!(mysql->options.charset_name= my_strdup(my_default_csname(),MYF(MY_WME))))
return 1; return 1;
return 0; return 0;
} }
@ -2204,16 +1967,13 @@ C_MODE_START
int mysql_init_character_set(MYSQL *mysql) int mysql_init_character_set(MYSQL *mysql)
{ {
/* Set character set */ /* Set character set */
if (!mysql->options.charset_name) if (!mysql->options.charset_name ||
!strcmp(mysql->options.charset_name,
MYSQL_AUTODETECT_CHARSET_NAME))
{ {
if (!(mysql->options.charset_name= if (mysql_autodetect_character_set(mysql))
my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
return 1; return 1;
} }
else if (!strcmp(mysql->options.charset_name,
MYSQL_AUTODETECT_CHARSET_NAME) &&
mysql_autodetect_character_set(mysql))
return 1;
mysql_set_character_set_with_default_collation(mysql); mysql_set_character_set_with_default_collation(mysql);

View file

@ -195,8 +195,7 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
info->table=table; info->table=table;
info->addon_field= addon_field; info->addon_field= addon_field;
if ((table->s->tmp_table == INTERNAL_TMP_TABLE || if ((table->s->tmp_table == INTERNAL_TMP_TABLE) &&
table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE) &&
!addon_field) !addon_field)
(void) table->file->extra(HA_EXTRA_MMAP); (void) table->file->extra(HA_EXTRA_MMAP);

View file

@ -700,19 +700,23 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
MDL_SHARED_NO_READ_WRITE lock (MDL_SHARED_WRITE cannot be upgraded) MDL_SHARED_NO_READ_WRITE lock (MDL_SHARED_WRITE cannot be upgraded)
by *not* having HA_CONCURRENT_OPTIMIZE table_flag. by *not* having HA_CONCURRENT_OPTIMIZE table_flag.
*/ */
if (lock_type == TL_WRITE && !table->table->s->tmp_table && if (lock_type == TL_WRITE && table->mdl_request.type > MDL_SHARED_WRITE)
table->mdl_request.type > MDL_SHARED_WRITE)
{ {
if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED)) if (table->table->s->tmp_table)
goto err; thd->close_unused_temporary_table_instances(tables);
DEBUG_SYNC(thd, "after_admin_flush"); else
/* Flush entries in the query cache involving this table. */ {
query_cache_invalidate3(thd, table->table, 0); if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED))
/* goto err;
XXX: hack: switch off open_for_modify to skip the DEBUG_SYNC(thd, "after_admin_flush");
flush that is made later in the execution flow. /* Flush entries in the query cache involving this table. */
*/ query_cache_invalidate3(thd, table->table, 0);
open_for_modify= 0; /*
XXX: hack: switch off open_for_modify to skip the
flush that is made later in the execution flow.
*/
open_for_modify= 0;
}
} }
if (table->table->s->crashed && operator_func == &handler::ha_check) if (table->table->s->crashed && operator_func == &handler::ha_check)

View file

@ -1786,12 +1786,15 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
} }
if (table->vfield) if (table->vfield)
{ {
my_bool abort_on_warning= thd->abort_on_warning;
/* /*
We have not yet called update_virtual_fields(VOL_UPDATE_FOR_READ) We have not yet called update_virtual_fields(VOL_UPDATE_FOR_READ)
in handler methods for the just read row in record[1]. in handler methods for the just read row in record[1].
*/ */
table->move_fields(table->field, table->record[1], table->record[0]); table->move_fields(table->field, table->record[1], table->record[0]);
thd->abort_on_warning= 0;
table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE); table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_REPLACE);
thd->abort_on_warning= abort_on_warning;
table->move_fields(table->field, table->record[0], table->record[1]); table->move_fields(table->field, table->record[0], table->record[1]);
} }
if (info->handle_duplicates == DUP_UPDATE) if (info->handle_duplicates == DUP_UPDATE)

View file

@ -791,8 +791,6 @@ void init_update_queries(void)
Note that SQLCOM_RENAME_TABLE should not be in this list! Note that SQLCOM_RENAME_TABLE should not be in this list!
*/ */
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_DROP_SEQUENCE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_TRUNCATE]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_TRUNCATE]|= CF_PREOPEN_TMP_TABLES;
@ -4743,7 +4741,14 @@ mysql_execute_command(THD *thd)
case SQLCOM_DROP_SEQUENCE: case SQLCOM_DROP_SEQUENCE:
case SQLCOM_DROP_TABLE: case SQLCOM_DROP_TABLE:
{ {
int result;
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
thd->open_options|= HA_OPEN_FOR_REPAIR;
result= thd->open_temporary_tables(all_tables);
thd->open_options&= ~HA_OPEN_FOR_REPAIR;
if (result)
goto error;
if (!lex->tmp_table()) if (!lex->tmp_table())
{ {
if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE)) if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE))

View file

@ -9845,6 +9845,8 @@ do_continue:;
DEBUG_SYNC(thd, "alter_table_copy_after_lock_upgrade"); DEBUG_SYNC(thd, "alter_table_copy_after_lock_upgrade");
} }
else
thd->close_unused_temporary_table_instances(table_list);
// It's now safe to take the table level lock. // It's now safe to take the table level lock.
if (lock_tables(thd, table_list, alter_ctx.tables_opened, if (lock_tables(thd, table_list, alter_ctx.tables_opened,

View file

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2016 MariaDB Corporation Copyright (c) 2016, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -395,6 +395,9 @@ bool THD::open_temporary_table(TABLE_LIST *tl)
rgi_slave->is_parallel_exec && rgi_slave->is_parallel_exec &&
wait_for_prior_commit()) wait_for_prior_commit())
DBUG_RETURN(true); DBUG_RETURN(true);
if (!table && is_error())
DBUG_RETURN(true); // Error when opening table
} }
if (!table) if (!table)

View file

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation. Copyright (c) 2018, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -358,6 +358,24 @@ public:
return(true); return(true);
} }
/**
Iterate over all the blocks in reverse and call the iterator
@return false if iteration was terminated. */
template <typename Functor>
bool for_each_block_in_reverse(const Functor& functor) const
{
for (block_t* block = UT_LIST_GET_LAST(m_list);
block != NULL;
block = UT_LIST_GET_PREV(m_node, block)) {
if (!functor(block)) {
return(false);
}
}
return(true);
}
/** /**
@return the first block */ @return the first block */
block_t* front() block_t* front()

View file

@ -525,7 +525,7 @@ struct mtr_t {
/** Check if this mini-transaction is dirtying a clean page. /** Check if this mini-transaction is dirtying a clean page.
@param block block being x-fixed @param block block being x-fixed
@return true if the mtr is dirtying a clean page. */ @return true if the mtr is dirtying a clean page. */
static bool is_block_dirtied(const buf_block_t* block) static inline bool is_block_dirtied(const buf_block_t* block)
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
private: private:

View file

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation. Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -26,6 +26,20 @@ Created 11/26/1995 Heikki Tuuri
#include "buf0buf.h" #include "buf0buf.h"
/** Check if a mini-transaction is dirtying a clean page.
@return true if the mtr is dirtying a clean page. */
bool
mtr_t::is_block_dirtied(const buf_block_t* block)
{
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_ad(block->page.buf_fix_count > 0);
/* It is OK to read oldest_modification because no
other thread can be performing a write of it and it
is only during write that the value is reset to 0. */
return(block->page.oldest_modification == 0);
}
/** /**
Pushes an object to an mtr memo stack. */ Pushes an object to an mtr memo stack. */
void void

View file

@ -38,7 +38,9 @@ enum mtr_log_t {
/** Default mode: log all operations modifying disk-based data */ /** Default mode: log all operations modifying disk-based data */
MTR_LOG_ALL = 21, MTR_LOG_ALL = 21,
/** Log no operations and dirty pages are not added to the flush list */ /** Log no operations and dirty pages are not added to the flush list.
Set when applying log in crash recovery or when a modification of a
ROW_FORMAT=COMPRESSED page is attempted. */
MTR_LOG_NONE = 22, MTR_LOG_NONE = 22,
/** Don't generate REDO log but add dirty pages to flush list */ /** Don't generate REDO log but add dirty pages to flush list */

View file

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation. Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -37,16 +37,43 @@ Created 11/26/1995 Heikki Tuuri
/** Iterate over a memo block in reverse. */ /** Iterate over a memo block in reverse. */
template <typename Functor> template <typename Functor>
struct Iterate { struct CIterate {
CIterate() : functor() {}
/** Release specific object */ CIterate(const Functor& functor) : functor(functor) {}
explicit Iterate(Functor& functor)
: /** @return false if the functor returns false. */
m_functor(functor) bool operator()(mtr_buf_t::block_t* block) const
{ {
/* Do nothing */ const mtr_memo_slot_t* start =
reinterpret_cast<const mtr_memo_slot_t*>(
block->begin());
mtr_memo_slot_t* slot =
reinterpret_cast<mtr_memo_slot_t*>(
block->end());
ut_ad(!(block->used() % sizeof(*slot)));
while (slot-- != start) {
if (!functor(slot)) {
return(false);
}
}
return(true);
} }
Functor functor;
};
template <typename Functor>
struct Iterate {
Iterate() : functor() {}
Iterate(const Functor& functor) : functor(functor) {}
/** @return false if the functor returns false. */ /** @return false if the functor returns false. */
bool operator()(mtr_buf_t::block_t* block) bool operator()(mtr_buf_t::block_t* block)
{ {
@ -62,7 +89,7 @@ struct Iterate {
while (slot-- != start) { while (slot-- != start) {
if (!m_functor(slot)) { if (!functor(slot)) {
return(false); return(false);
} }
} }
@ -70,7 +97,7 @@ struct Iterate {
return(true); return(true);
} }
Functor& m_functor; Functor functor;
}; };
/** Find specific object */ /** Find specific object */
@ -430,20 +457,6 @@ private:
lsn_t m_end_lsn; lsn_t m_end_lsn;
}; };
/** Check if a mini-transaction is dirtying a clean page.
@return true if the mtr is dirtying a clean page. */
bool
mtr_t::is_block_dirtied(const buf_block_t* block)
{
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_ad(block->page.buf_fix_count > 0);
/* It is OK to read oldest_modification because no
other thread can be performing a write of it and it
is only during write that the value is reset to 0. */
return(block->page.oldest_modification == 0);
}
/** Write the block contents to the REDO log */ /** Write the block contents to the REDO log */
struct mtr_write_log_t { struct mtr_write_log_t {
/** Append a block to the redo log buffer. /** Append a block to the redo log buffer.
@ -509,12 +522,7 @@ mtr_t::Command::release_resources()
/* Currently only used in commit */ /* Currently only used in commit */
ut_ad(m_impl->m_state == MTR_STATE_COMMITTING); ut_ad(m_impl->m_state == MTR_STATE_COMMITTING);
#ifdef UNIV_DEBUG ut_d(m_impl->m_memo.for_each_block_in_reverse(CIterate<DebugCheck>()));
DebugCheck release;
Iterate<DebugCheck> iterator(release);
m_impl->m_memo.for_each_block_in_reverse(iterator);
#endif /* UNIV_DEBUG */
/* Reset the mtr buffers */ /* Reset the mtr buffers */
m_impl->m_log.erase(); m_impl->m_log.erase();
@ -702,11 +710,10 @@ mtr_t::memo_release(const void* object, ulint type)
middle of a mini-transaction. */ middle of a mini-transaction. */
ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX); ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX);
Find find(object, type); Iterate<Find> iteration(Find(object, type));
Iterate<Find> iterator(find);
if (!m_impl.m_memo.for_each_block_in_reverse(iterator)) { if (!m_impl.m_memo.for_each_block_in_reverse(iteration)) {
memo_slot_release(find.m_slot); memo_slot_release(iteration.functor.m_slot);
return(true); return(true);
} }
@ -726,11 +733,10 @@ mtr_t::release_page(const void* ptr, mtr_memo_type_t type)
middle of a mini-transaction. */ middle of a mini-transaction. */
ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX); ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX);
FindPage find(ptr, type); Iterate<FindPage> iteration(FindPage(ptr, type));
Iterate<FindPage> iterator(find);
if (!m_impl.m_memo.for_each_block_in_reverse(iterator)) { if (!m_impl.m_memo.for_each_block_in_reverse(iteration)) {
memo_slot_release(find.get_slot()); memo_slot_release(iteration.functor.get_slot());
return; return;
} }
@ -854,10 +860,7 @@ mtr_t::Command::finish_write(
void void
mtr_t::Command::release_all() mtr_t::Command::release_all()
{ {
ReleaseAll release; m_impl->m_memo.for_each_block_in_reverse(CIterate<ReleaseAll>());
Iterate<ReleaseAll> iterator(release);
m_impl->m_memo.for_each_block_in_reverse(iterator);
/* Note that we have released the latches. */ /* Note that we have released the latches. */
m_locks_released = 1; m_locks_released = 1;
@ -867,10 +870,7 @@ mtr_t::Command::release_all()
void void
mtr_t::Command::release_latches() mtr_t::Command::release_latches()
{ {
ReleaseLatches release; m_impl->m_memo.for_each_block_in_reverse(CIterate<ReleaseLatches>());
Iterate<ReleaseLatches> iterator(release);
m_impl->m_memo.for_each_block_in_reverse(iterator);
/* Note that we have released the latches. */ /* Note that we have released the latches. */
m_locks_released = 1; m_locks_released = 1;
@ -880,10 +880,10 @@ mtr_t::Command::release_latches()
void void
mtr_t::Command::release_blocks() mtr_t::Command::release_blocks()
{ {
ReleaseBlocks release(m_start_lsn, m_end_lsn, m_impl->m_flush_observer); m_impl->m_memo.for_each_block_in_reverse(
Iterate<ReleaseBlocks> iterator(release); CIterate<const ReleaseBlocks>(
ReleaseBlocks(m_start_lsn, m_end_lsn,
m_impl->m_memo.for_each_block_in_reverse(iterator); m_impl->m_flush_observer)));
} }
/** Write the redo log record, add dirty pages to the flush list and release /** Write the redo log record, add dirty pages to the flush list and release
@ -928,10 +928,8 @@ mtr_t::memo_contains(
const void* object, const void* object,
ulint type) ulint type)
{ {
Find find(object, type); Iterate<Find> iteration(Find(object, type));
Iterate<Find> iterator(find); if (memo->for_each_block_in_reverse(iteration)) {
if (memo->for_each_block_in_reverse(iterator)) {
return(false); return(false);
} }
@ -1020,10 +1018,8 @@ mtr_t::memo_contains_flagged(const void* ptr, ulint flags) const
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(is_committing() || is_active()); ut_ad(is_committing() || is_active());
FlaggedCheck check(ptr, flags); return !m_impl.m_memo.for_each_block_in_reverse(
Iterate<FlaggedCheck> iterator(check); CIterate<FlaggedCheck>(FlaggedCheck(ptr, flags)));
return(!m_impl.m_memo.for_each_block_in_reverse(iterator));
} }
/** Check if memo contains the given page. /** Check if memo contains the given page.
@ -1037,11 +1033,9 @@ mtr_t::memo_contains_page_flagged(
const byte* ptr, const byte* ptr,
ulint flags) const ulint flags) const
{ {
FindPage check(ptr, flags); Iterate<FindPage> iteration(FindPage(ptr, flags));
Iterate<FindPage> iterator(check); return m_impl.m_memo.for_each_block_in_reverse(iteration)
? NULL : iteration.functor.get_block();
return(m_impl.m_memo.for_each_block_in_reverse(iterator)
? NULL : check.get_block());
} }
/** Mark the given latched page as modified. /** Mark the given latched page as modified.

View file

@ -1217,6 +1217,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
if (!file || !param) return HA_ADMIN_INTERNAL_ERROR; if (!file || !param) return HA_ADMIN_INTERNAL_ERROR;
unmap_file(file);
maria_chk_init(param); maria_chk_init(param);
param->thd= thd; param->thd= thd;
param->op_name= "check"; param->op_name= "check";
@ -1437,6 +1438,7 @@ int ha_maria::zerofill(THD * thd, HA_CHECK_OPT *check_opt)
if (!file || !param) if (!file || !param)
return HA_ADMIN_INTERNAL_ERROR; return HA_ADMIN_INTERNAL_ERROR;
unmap_file(file);
old_trn= file->trn; old_trn= file->trn;
maria_chk_init(param); maria_chk_init(param);
param->thd= thd; param->thd= thd;
@ -1535,6 +1537,7 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize)
param->out_flag= 0; param->out_flag= 0;
share->state.dupp_key= MI_MAX_KEY; share->state.dupp_key= MI_MAX_KEY;
strmov(fixed_name, share->open_file_name.str); strmov(fixed_name, share->open_file_name.str);
unmap_file(file);
/* /*
Don't lock tables if we have used LOCK TABLE or if we come from Don't lock tables if we have used LOCK TABLE or if we come from
@ -1714,7 +1717,6 @@ int ha_maria::assign_to_keycache(THD * thd, HA_CHECK_OPT *check_opt)
TABLE_LIST *table_list= table->pos_in_table_list; TABLE_LIST *table_list= table->pos_in_table_list;
DBUG_ENTER("ha_maria::assign_to_keycache"); DBUG_ENTER("ha_maria::assign_to_keycache");
table->keys_in_use_for_query.clear_all(); table->keys_in_use_for_query.clear_all();
if (table_list->process_index_hints(table)) if (table_list->process_index_hints(table))
@ -2669,7 +2671,8 @@ int ha_maria::external_lock(THD *thd, int lock_type)
} }
else else
{ {
TRN *trn= (file->trn != &dummy_transaction_object ? file->trn : 0); /* We have to test for THD_TRN to protect against implicit commits */
TRN *trn= (file->trn != &dummy_transaction_object && THD_TRN ? file->trn : 0);
/* End of transaction */ /* End of transaction */
/* /*

View file

@ -5244,6 +5244,8 @@ my_bool _ma_scan_init_block_record(MARIA_HA *info)
{ {
MARIA_SHARE *share= info->s; MARIA_SHARE *share= info->s;
DBUG_ENTER("_ma_scan_init_block_record"); DBUG_ENTER("_ma_scan_init_block_record");
DBUG_ASSERT(info->dfile.file == share->bitmap.file.file);
/* /*
bitmap_buff may already be allocated if this is the second call to bitmap_buff may already be allocated if this is the second call to
rnd_init() without a rnd_end() in between, see sql/handler.h rnd_init() without a rnd_end() in between, see sql/handler.h

View file

@ -113,10 +113,7 @@ int maria_close(register MARIA_HA *info)
if (flush_pagecache_blocks(share->pagecache, &share->kfile, if (flush_pagecache_blocks(share->pagecache, &share->kfile,
share->deleting ? FLUSH_IGNORE_CHANGED : FLUSH_RELEASE)) share->deleting ? FLUSH_IGNORE_CHANGED : FLUSH_RELEASE))
error= my_errno; error= my_errno;
#ifdef HAVE_MMAP unmap_file(info);
if (share->file_map)
_ma_unmap_file(info);
#endif
if (((share->changed && share->base.born_transactional) || if (((share->changed && share->base.born_transactional) ||
maria_is_crashed(info) || (share->temporary && !share->deleting))) maria_is_crashed(info) || (share->temporary && !share->deleting)))
{ {

View file

@ -38,6 +38,9 @@ int maria_delete_all_rows(MARIA_HA *info)
MARIA_SHARE *share= info->s; MARIA_SHARE *share= info->s;
my_bool log_record; my_bool log_record;
LSN lsn; LSN lsn;
#ifdef HAVE_MMAP
my_bool mmap_file= share->file_map != 0;
#endif
DBUG_ENTER("maria_delete_all_rows"); DBUG_ENTER("maria_delete_all_rows");
if (share->options & HA_OPTION_READ_ONLY_DATA) if (share->options & HA_OPTION_READ_ONLY_DATA)
@ -95,7 +98,7 @@ int maria_delete_all_rows(MARIA_HA *info)
*/ */
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
if (share->file_map) if (mmap_file)
_ma_unmap_file(info); _ma_unmap_file(info);
#endif #endif
@ -141,7 +144,7 @@ int maria_delete_all_rows(MARIA_HA *info)
_ma_writeinfo(info, WRITEINFO_UPDATE_KEYFILE); _ma_writeinfo(info, WRITEINFO_UPDATE_KEYFILE);
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
/* Map again */ /* Map again */
if (share->file_map) if (mmap_file)
_ma_dynmap_file(info, (my_off_t) 0); _ma_dynmap_file(info, (my_off_t) 0);
#endif #endif
DBUG_RETURN(0); DBUG_RETURN(0);

View file

@ -1564,8 +1564,13 @@ my_bool _ma_memmap_file(MARIA_HA *info)
void _ma_unmap_file(MARIA_HA *info) void _ma_unmap_file(MARIA_HA *info)
{ {
my_munmap((char*) info->s->file_map, MARIA_SHARE *share= info->s;
(size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN); my_munmap((char*) share->file_map,
(size_t) share->mmaped_length + MEMMAP_EXTRA_MARGIN);
share->file_map= 0;
share->file_read= _ma_nommap_pread;
share->file_write= _ma_nommap_pwrite;
info->opt_flag&= ~MEMMAP_USED;
} }

View file

@ -3464,8 +3464,6 @@ restart:
pagecache_pthread_mutex_lock(&pagecache->cache_lock); pagecache_pthread_mutex_lock(&pagecache->cache_lock);
#endif #endif
} }
if (status & PCBLOCK_ERROR)
my_errno= block->error;
} }
remove_reader(block); remove_reader(block);
@ -3497,6 +3495,7 @@ restart:
if (status & PCBLOCK_ERROR) if (status & PCBLOCK_ERROR)
{ {
my_errno= block->error;
DBUG_ASSERT(my_errno != 0); DBUG_ASSERT(my_errno != 0);
DBUG_PRINT("error", ("Got error %d when doing page read", my_errno)); DBUG_PRINT("error", ("Got error %d when doing page read", my_errno));
DBUG_RETURN((uchar *) 0); DBUG_RETURN((uchar *) 0);

View file

@ -1432,3 +1432,11 @@ extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx);
extern my_bool ma_killed_standalone(MARIA_HA *); extern my_bool ma_killed_standalone(MARIA_HA *);
extern uint _ma_file_callback_to_id(void *callback_data); extern uint _ma_file_callback_to_id(void *callback_data);
static inline void unmap_file(MARIA_HA *info __attribute__((unused)))
{
#ifdef HAVE_MMAP
if (info->s->file_map)
_ma_unmap_file(info);
#endif
}

View file

@ -11029,6 +11029,41 @@ void ha_rocksdb::read_thd_vars(THD *const thd) {
m_checksums_pct = THDVAR(thd, checksums_pct); m_checksums_pct = THDVAR(thd, checksums_pct);
} }
ulonglong ha_rocksdb::table_flags() const
{
DBUG_ENTER_FUNC();
/*
HA_BINLOG_STMT_CAPABLE
Upstream: MyRocks advertises itself as it supports SBR, but has additional
checks in ha_rocksdb::external_lock()/ start_stmt() which will return an
error if one tries to run the statement.
Exceptions: @@rocksdb_unsafe_for_binlog or we are an SQL slave thread.
MariaDB: Inform the upper layer we don't support SBR, so it switches to RBR
if possible. The exceptions are the same as with the upstream.
HA_REC_NOT_IN_SEQ
If we don't set it, filesort crashes, because it assumes rowids are
1..8 byte numbers
HA_PRIMARY_KEY_IN_READ_INDEX
This flag is always set, even for tables that:
- have no PK
- have some (or all) of PK that can't be decoded from the secondary
index.
*/
THD *thd= ha_thd();
DBUG_RETURN(HA_BINLOG_ROW_CAPABLE |
((thd && (THDVAR(thd, unsafe_for_binlog) ||thd->rgi_slave))?
HA_BINLOG_STMT_CAPABLE : 0) |
HA_REC_NOT_IN_SEQ | HA_CAN_INDEX_BLOBS |
HA_PRIMARY_KEY_IN_READ_INDEX |
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_NULL_IN_KEY |
HA_PARTIAL_COLUMN_READ |
HA_TABLE_SCAN_ON_INDEX);
}
/** /**
@return @return
@ -11041,6 +11076,9 @@ int ha_rocksdb::external_lock(THD *const thd, int lock_type) {
DBUG_ASSERT(thd != nullptr); DBUG_ASSERT(thd != nullptr);
int res = HA_EXIT_SUCCESS; int res = HA_EXIT_SUCCESS;
#if 0
// MariaDB uses a different way to implement this, see ha_rocksdb::table_flags
int binlog_format = my_core::thd_binlog_format(thd); int binlog_format = my_core::thd_binlog_format(thd);
bool unsafe_for_binlog = THDVAR(ha_thd(), unsafe_for_binlog); bool unsafe_for_binlog = THDVAR(ha_thd(), unsafe_for_binlog);
@ -11069,6 +11107,7 @@ int ha_rocksdb::external_lock(THD *const thd, int lock_type) {
my_error(ER_REQUIRE_ROW_BINLOG_FORMAT, MYF(0)); my_error(ER_REQUIRE_ROW_BINLOG_FORMAT, MYF(0));
DBUG_RETURN(HA_ERR_UNSUPPORTED); DBUG_RETURN(HA_ERR_UNSUPPORTED);
} }
#endif
if (lock_type == F_UNLCK) { if (lock_type == F_UNLCK) {
Rdb_transaction *const tx = get_tx_from_thd(thd); Rdb_transaction *const tx = get_tx_from_thd(thd);
@ -11171,20 +11210,6 @@ int ha_rocksdb::external_lock(THD *const thd, int lock_type) {
int ha_rocksdb::start_stmt(THD *const thd, thr_lock_type lock_type) { int ha_rocksdb::start_stmt(THD *const thd, thr_lock_type lock_type) {
DBUG_ENTER_FUNC(); DBUG_ENTER_FUNC();
/*
MariaDB: the following is a copy of the check in ha_rocksdb::external_lock:
*/
int binlog_format = my_core::thd_binlog_format(thd);
bool unsafe_for_binlog = THDVAR(ha_thd(), unsafe_for_binlog);
if (lock_type >= TL_WRITE_ALLOW_WRITE &&
!thd->rgi_slave && !unsafe_for_binlog &&
binlog_format != BINLOG_FORMAT_ROW &&
binlog_format != BINLOG_FORMAT_UNSPEC &&
my_core::thd_binlog_filter_ok(thd)) {
my_error(ER_REQUIRE_ROW_BINLOG_FORMAT, MYF(0));
DBUG_RETURN(HA_ERR_UNSUPPORTED);
}
DBUG_ASSERT(thd != nullptr); DBUG_ASSERT(thd != nullptr);
Rdb_transaction *const tx = get_or_create_tx(thd); Rdb_transaction *const tx = get_or_create_tx(thd);

View file

@ -863,31 +863,7 @@ public:
This is a list of flags that indicate what functionality the storage engine This is a list of flags that indicate what functionality the storage engine
implements. The current table flags are documented in handler.h implements. The current table flags are documented in handler.h
*/ */
ulonglong table_flags() const override { ulonglong table_flags() const override ;
DBUG_ENTER_FUNC();
/*
HA_BINLOG_STMT_CAPABLE
We are saying that this engine is just statement capable to have
an engine that can only handle statement-based logging. This is
used in testing.
HA_REC_NOT_IN_SEQ
If we don't set it, filesort crashes, because it assumes rowids are
1..8 byte numbers
HA_PRIMARY_KEY_IN_READ_INDEX
This flag is always set, even for tables that:
- have no PK
- have some (or all) of PK that can't be decoded from the secondary
index.
*/
DBUG_RETURN(HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_REC_NOT_IN_SEQ | HA_CAN_INDEX_BLOBS |
HA_PRIMARY_KEY_IN_READ_INDEX |
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_NULL_IN_KEY |
HA_PARTIAL_COLUMN_READ |
HA_TABLE_SCAN_ON_INDEX);
}
private: private:
bool init_with_fields(); /* no 'override' in MariaDB */ bool init_with_fields(); /* no 'override' in MariaDB */
public: public:

View file

@ -18,7 +18,16 @@ set @tmp_bf= @@binlog_format;
set binlog_format='STATEMENT'; set binlog_format='STATEMENT';
lock tables t1 write; lock tables t1 write;
insert into t1 values(1); insert into t1 values(1);
ERROR HY000: Can't execute updates on master with binlog_format != ROW. ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging.
unlock tables; unlock tables;
set @@binlog_format=@tmp_bf; set @@binlog_format=@tmp_bf;
drop table t1; drop table t1;
#
# MDEV-17045: MyRocks tables cannot be updated when binlog_format=MIXED.
#
set @tmp_bf= @@binlog_format;
set binlog_format='MIXED';
create table t1 (pk int primary key) engine=rocksdb;
insert into t1 values (1);
drop table t1;
set @@binlog_format=@tmp_bf;

View file

@ -8,7 +8,7 @@ select @@binlog_format;
STATEMENT STATEMENT
create table t1 (pk int primary key) engine=rocksdb; create table t1 (pk int primary key) engine=rocksdb;
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
ERROR HY000: Can't execute updates on master with binlog_format != ROW. ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging.
set session rocksdb_unsafe_for_binlog=on; set session rocksdb_unsafe_for_binlog=on;
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
select * from t1; select * from t1;
@ -19,7 +19,7 @@ pk
delete from t1; delete from t1;
set session rocksdb_unsafe_for_binlog=off; set session rocksdb_unsafe_for_binlog=off;
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
ERROR HY000: Can't execute updates on master with binlog_format != ROW. ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging.
set binlog_format=row; set binlog_format=row;
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
include/sync_slave_sql_with_master.inc include/sync_slave_sql_with_master.inc

View file

@ -21,10 +21,20 @@ unlock tables;
set @tmp_bf= @@binlog_format; set @tmp_bf= @@binlog_format;
set binlog_format='STATEMENT'; set binlog_format='STATEMENT';
lock tables t1 write; lock tables t1 write;
--error ER_REQUIRE_ROW_BINLOG_FORMAT --error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
insert into t1 values(1); insert into t1 values(1);
unlock tables; unlock tables;
set @@binlog_format=@tmp_bf; set @@binlog_format=@tmp_bf;
drop table t1; drop table t1;
--echo #
--echo # MDEV-17045: MyRocks tables cannot be updated when binlog_format=MIXED.
--echo #
set @tmp_bf= @@binlog_format;
set binlog_format='MIXED';
create table t1 (pk int primary key) engine=rocksdb;
insert into t1 values (1);
drop table t1;
set @@binlog_format=@tmp_bf;

View file

@ -12,7 +12,7 @@ connection master;
select @@binlog_format; select @@binlog_format;
create table t1 (pk int primary key) engine=rocksdb; create table t1 (pk int primary key) engine=rocksdb;
--error ER_REQUIRE_ROW_BINLOG_FORMAT --error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
set session rocksdb_unsafe_for_binlog=on; set session rocksdb_unsafe_for_binlog=on;
@ -21,7 +21,7 @@ select * from t1;
delete from t1; delete from t1;
set session rocksdb_unsafe_for_binlog=off; set session rocksdb_unsafe_for_binlog=off;
--error ER_REQUIRE_ROW_BINLOG_FORMAT --error ER_BINLOG_STMT_MODE_AND_ROW_ENGINE
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
set binlog_format=row; set binlog_format=row;