summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-10-13 12:03:32 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-10-13 12:03:32 +0300
commita736a3174a4e7c0d92a38901ae61f563d4afede7 (patch)
tree348d15f7c9cc883e86d852fbddc780f506669ee4
parentb44e12fef176bfc0884fb2c5f4ba7f42bf054f44 (diff)
parent4a7dfda373ff9e28e4f4f35bad76cbfc20934a9a (diff)
downloadmariadb-git-a736a3174a4e7c0d92a38901ae61f563d4afede7.tar.gz
Merge 10.3 into 10.4
-rw-r--r--.gitignore3
-rw-r--r--client/mysql.cc24
-rw-r--r--include/ft_global.h3
-rw-r--r--include/my_context.h3
-rw-r--r--include/my_global.h2
-rw-r--r--include/mysql_com.h6
-rw-r--r--man/mysql.19
-rw-r--r--mysql-test/main/ctype_utf16_def.result5
-rw-r--r--mysql-test/main/ctype_utf16_def.test7
-rw-r--r--mysql-test/main/ctype_utf32_def.opt1
-rw-r--r--mysql-test/main/ctype_utf32_def.result6
-rw-r--r--mysql-test/main/ctype_utf32_def.test9
-rw-r--r--mysql-test/main/default.result9
-rw-r--r--mysql-test/main/default.test9
-rw-r--r--mysql-test/main/delayed_blob.opt1
-rw-r--r--mysql-test/main/delayed_blob.result17
-rw-r--r--mysql-test/main/delayed_blob.test21
-rw-r--r--mysql-test/main/func_str.result12
-rw-r--r--mysql-test/main/func_str.test16
-rw-r--r--mysql-test/main/invisible_field.result17
-rw-r--r--mysql-test/main/invisible_field.test13
-rw-r--r--mysql-test/main/multi_update.result10
-rw-r--r--mysql-test/main/multi_update.test11
-rw-r--r--mysql-test/main/mysql_binary_zero_insert.result54
-rw-r--r--mysql-test/main/mysql_binary_zero_insert.test170
-rw-r--r--mysql-test/suite/innodb/r/mdev-14846.result52
-rw-r--r--mysql-test/suite/innodb/t/mdev-14846.opt1
-rw-r--r--mysql-test/suite/innodb/t/mdev-14846.test70
-rw-r--r--mysql-test/suite/plugins/r/feedback_plugin_send.result20
-rw-r--r--mysql-test/suite/plugins/t/feedback_plugin_send.test2
-rw-r--r--mysql-test/suite/versioning/r/alter.result19
-rw-r--r--mysql-test/suite/versioning/t/alter.test22
-rw-r--r--mysys/my_context.c7
-rw-r--r--sql/field.cc2
-rw-r--r--sql/field.h13
-rw-r--r--sql/handler.cc90
-rw-r--r--sql/item_strfunc.cc2
-rw-r--r--sql/item_vers.cc2
-rw-r--r--sql/mysqld.cc4
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_explain.h2
-rw-r--r--sql/sql_insert.cc11
-rw-r--r--sql/sql_lex.cc4
-rw-r--r--sql/sql_select.cc44
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_table.cc6
-rw-r--r--sql/sql_type.cc2
-rw-r--r--sql/sys_vars.cc4
-rw-r--r--sql/table.cc7
-rw-r--r--storage/connect/bsonudf.cpp9
-rw-r--r--storage/connect/inihandl.cpp8
-rw-r--r--storage/connect/tabbson.cpp2
-rw-r--r--storage/innobase/log/log0log.cc11
-rw-r--r--storage/myisam/ft_parser.c13
54 files changed, 754 insertions, 121 deletions
diff --git a/.gitignore b/.gitignore
index b3cbd1d430d..99c47b46966 100644
--- a/.gitignore
+++ b/.gitignore
@@ -373,6 +373,7 @@ x86/
build/
bld/
[Bb]in/
+/cmake-build-debug/
[Oo]bj/
# Roslyn cache directories
@@ -555,7 +556,7 @@ compile_commands.json
.vscode/
# Clion && other JetBrains ides
-.idea
+/.idea/
.cache/clangd
diff --git a/client/mysql.cc b/client/mysql.cc
index 7b3f34b755f..5db52a3ef36 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1672,11 +1672,14 @@ static struct my_option my_long_options[] =
&opt_default_auth, &opt_default_auth, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"binary-mode", 0,
- "By default, ASCII '\\0' is disallowed and '\\r\\n' is translated to '\\n'. "
- "This switch turns off both features, and also turns off parsing of all client"
- "commands except \\C and DELIMITER, in non-interactive mode (for input "
- "piped to mysql or loaded using the 'source' command). This is necessary "
- "when processing output from mysqlbinlog that may contain blobs.",
+ "Binary mode allows certain character sequences to be processed as data "
+ "that would otherwise be treated with a special meaning by the parser. "
+ "Specifically, this switch turns off parsing of all client commands except "
+ "\\C and DELIMITER in non-interactive mode (i.e., when binary mode is "
+ "combined with either 1) piped input, 2) the --batch mysql option, or 3) "
+ "the 'source' command). Also, in binary mode, occurrences of '\\r\\n' and "
+ "ASCII '\\0' are preserved within strings, whereas by default, '\\r\\n' is "
+ "translated to '\\n' and '\\0' is disallowed in user input.",
&opt_binary_mode, &opt_binary_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"connect-expired-password", 0,
"Notify the server that this client is prepared to handle expired "
@@ -2316,8 +2319,15 @@ static bool add_line(String &buffer, char *line, size_t line_length,
{
// Found possbile one character command like \c
- if (!(inchar = (uchar) *++pos))
- break; // readline adds one '\'
+ /*
+ The null-terminating character (ASCII '\0') marks the end of user
+ input. Then, by default, upon encountering a '\0' while parsing, it
+ should stop. However, some data naturally contains binary zeros
+ (e.g., zipped files). Real_binary_mode signals the parser to expect
+ '\0' within the data and not to end parsing if found.
+ */
+ if (!(inchar = (uchar) *++pos) && (!real_binary_mode || !*in_string))
+ break; // readline adds one '\'
if (*in_string || inchar == 'N') // \N is short for NULL
{ // Don't allow commands in string
*out++='\\';
diff --git a/include/ft_global.h b/include/ft_global.h
index 725363c3aa8..9f2d52610ba 100644
--- a/include/ft_global.h
+++ b/include/ft_global.h
@@ -90,7 +90,8 @@ void ft_free_stopwords(void);
FT_INFO *ft_init_search(uint,void *, uint, uchar *, size_t,
CHARSET_INFO *, uchar *);
-my_bool ft_boolean_check_syntax_string(const uchar *);
+my_bool ft_boolean_check_syntax_string(const uchar *, size_t length,
+ CHARSET_INFO *cs);
/* Internal symbols for fulltext between maria and MyISAM */
diff --git a/include/my_context.h b/include/my_context.h
index ea0e3496887..45d2a7d7ffa 100644
--- a/include/my_context.h
+++ b/include/my_context.h
@@ -52,6 +52,9 @@ struct my_context {
#ifdef MY_CONTEXT_USE_UCONTEXT
+#if defined(__APPLE__) && !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE
+#endif
#include <ucontext.h>
struct my_context {
diff --git a/include/my_global.h b/include/my_global.h
index ae8835a2a50..a4c694fd196 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -159,7 +159,7 @@
# if defined(__i386__) || defined(__ppc__)
# define SIZEOF_CHARP 4
# define SIZEOF_LONG 4
-# elif defined(__x86_64__) || defined(__ppc64__)
+# elif defined(__x86_64__) || defined(__ppc64__) || defined(__aarch64__)
# define SIZEOF_CHARP 8
# define SIZEOF_LONG 8
# else
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 65f686f3063..f63cf0ac5c2 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -193,13 +193,13 @@ enum enum_indicator_type
#define FIELD_FLAGS_COLUMN_FORMAT_MASK (3U << FIELD_FLAGS_COLUMN_FORMAT)
#define FIELD_IS_DROPPED (1U << 26) /* Intern: Field is being dropped */
-#define VERS_SYS_START_FLAG (1 << 27) /* autogenerated column declared with
+#define VERS_ROW_START (1 << 27) /* autogenerated column declared with
`generated always as row start`
(see II.a SQL Standard) */
-#define VERS_SYS_END_FLAG (1 << 28) /* autogenerated column declared with
+#define VERS_ROW_END (1 << 28) /* autogenerated column declared with
`generated always as row end`
(see II.a SQL Standard).*/
-#define VERS_SYSTEM_FIELD (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG)
+#define VERS_SYSTEM_FIELD (VERS_ROW_START | VERS_ROW_END)
#define VERS_UPDATE_UNVERSIONED_FLAG (1 << 29) /* column that doesn't support
system versioning when table
itself supports it*/
diff --git a/man/mysql.1 b/man/mysql.1
index c2eda6d7e72..2acb71656a0 100644
--- a/man/mysql.1
+++ b/man/mysql.1
@@ -206,7 +206,14 @@ option\&.
.\" binary-mode option: mysql
\fB\-\-binary\-mode\fR
.sp
-By default, ASCII '\e0' is disallowed and '\er\en' is translated to '\en'\&. This switch turns off both features, and also turns off parsing of all client commands except \eC and DELIMITER, in non-interactive mode (for input piped to mysql or loaded using the 'source' command)\&. This is necessary when processing output from mysqlbinlog that may contain blobs\&.
+Binary mode allows certain character sequences to be processed as data that
+would otherwise be treated with a special meaning by the parser\&.
+Specifically, this switch turns off parsing of all client commands except \eC
+and DELIMITER in non-interactive mode (i\&.e\&., when binary mode is combined
+with either 1) piped input, 2) the --batch mysql option, or 3) the 'source'
+command)\&. Also, in binary mode, occurrences of '\er\en' and ASCII '\e0' are
+preserved within strings, whereas by default, '\er\en' is translated to '\en'
+and '\e0' is disallowed in user input\&.
.RE
.sp
.RS 4
diff --git a/mysql-test/main/ctype_utf16_def.result b/mysql-test/main/ctype_utf16_def.result
index 98b6f7d913d..b5827d45619 100644
--- a/mysql-test/main/ctype_utf16_def.result
+++ b/mysql-test/main/ctype_utf16_def.result
@@ -8,3 +8,8 @@ character_set_server utf16
SHOW VARIABLES LIKE 'ft_stopword_file';
Variable_name Value
ft_stopword_file (built-in)
+#
+# MDEV-23269 SIGSEGV in ft_boolean_check_syntax_string on setting ft_boolean_syntax
+#
+SET GLOBAL ft_boolean_syntax='+ -><()~*:""&|';
+SET GLOBAL ft_boolean_syntax=DEFAULT;
diff --git a/mysql-test/main/ctype_utf16_def.test b/mysql-test/main/ctype_utf16_def.test
index 0829cd53285..c6de842f618 100644
--- a/mysql-test/main/ctype_utf16_def.test
+++ b/mysql-test/main/ctype_utf16_def.test
@@ -7,3 +7,10 @@ call mtr.add_suppression("'utf16' can not be used as client character set");
SHOW VARIABLES LIKE 'collation_server';
SHOW VARIABLES LIKE 'character_set_server';
SHOW VARIABLES LIKE 'ft_stopword_file';
+
+--echo #
+--echo # MDEV-23269 SIGSEGV in ft_boolean_check_syntax_string on setting ft_boolean_syntax
+--echo #
+
+SET GLOBAL ft_boolean_syntax='+ -><()~*:""&|';
+SET GLOBAL ft_boolean_syntax=DEFAULT;
diff --git a/mysql-test/main/ctype_utf32_def.opt b/mysql-test/main/ctype_utf32_def.opt
new file mode 100644
index 00000000000..3b0880cbff3
--- /dev/null
+++ b/mysql-test/main/ctype_utf32_def.opt
@@ -0,0 +1 @@
+--character-set-server=utf32,latin1 --collation-server=utf32_general_ci
diff --git a/mysql-test/main/ctype_utf32_def.result b/mysql-test/main/ctype_utf32_def.result
new file mode 100644
index 00000000000..611072eb75b
--- /dev/null
+++ b/mysql-test/main/ctype_utf32_def.result
@@ -0,0 +1,6 @@
+call mtr.add_suppression("'utf32' can not be used as client character set");
+#
+# MDEV-23269 SIGSEGV in ft_boolean_check_syntax_string on setting ft_boolean_syntax
+#
+SET GLOBAL ft_boolean_syntax='+ -><()~*:""&|';
+SET GLOBAL ft_boolean_syntax=DEFAULT;
diff --git a/mysql-test/main/ctype_utf32_def.test b/mysql-test/main/ctype_utf32_def.test
new file mode 100644
index 00000000000..e23f96052d3
--- /dev/null
+++ b/mysql-test/main/ctype_utf32_def.test
@@ -0,0 +1,9 @@
+--source include/have_utf32.inc
+call mtr.add_suppression("'utf32' can not be used as client character set");
+
+--echo #
+--echo # MDEV-23269 SIGSEGV in ft_boolean_check_syntax_string on setting ft_boolean_syntax
+--echo #
+
+SET GLOBAL ft_boolean_syntax='+ -><()~*:""&|';
+SET GLOBAL ft_boolean_syntax=DEFAULT;
diff --git a/mysql-test/main/default.result b/mysql-test/main/default.result
index 0d2c2e6acbc..e8f5bd8e48a 100644
--- a/mysql-test/main/default.result
+++ b/mysql-test/main/default.result
@@ -3387,6 +3387,14 @@ CREATE OR REPLACE TABLE t1(i int);
ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;
ERROR 42S22: Unknown column 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in 'DEFAULT'
DROP TABLE t1;
+#
+# MDEV-18278 Misleading error message in error log upon failed table creation
+#
+create table t1 (a int as (a));
+ERROR 01000: Expression for field `a` is referring to uninitialized field `a`
+show warnings;
+Level Code Message
+Error 4029 Expression for field `a` is referring to uninitialized field `a`
# end of 10.2 test
#
# MDEV-22703 DEFAULT() on a BLOB column can overwrite the default
@@ -3403,3 +3411,4 @@ length(DEFAULT(h))
25
INSERT INTO t1 () VALUES ();
drop table t1;
+# end of 10.3 test
diff --git a/mysql-test/main/default.test b/mysql-test/main/default.test
index c0561deac67..bcd6ef7a9fb 100644
--- a/mysql-test/main/default.test
+++ b/mysql-test/main/default.test
@@ -2109,6 +2109,13 @@ CREATE OR REPLACE TABLE t1(i int);
ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;
DROP TABLE t1;
+--echo #
+--echo # MDEV-18278 Misleading error message in error log upon failed table creation
+--echo #
+--error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD
+create table t1 (a int as (a));
+show warnings;
+
--echo # end of 10.2 test
--echo #
@@ -2126,3 +2133,5 @@ SELECT DEFAULT(h) FROM t1;
SELECT length(DEFAULT(h)) FROM t1;
INSERT INTO t1 () VALUES ();
drop table t1;
+
+--echo # end of 10.3 test
diff --git a/mysql-test/main/delayed_blob.opt b/mysql-test/main/delayed_blob.opt
new file mode 100644
index 00000000000..e442a822046
--- /dev/null
+++ b/mysql-test/main/delayed_blob.opt
@@ -0,0 +1 @@
+--init_connect="set @a='something unique to have MTR start a dedicated mariadbd for this test and shutdown it after the test'"
diff --git a/mysql-test/main/delayed_blob.result b/mysql-test/main/delayed_blob.result
new file mode 100644
index 00000000000..caa2e3ae5fe
--- /dev/null
+++ b/mysql-test/main/delayed_blob.result
@@ -0,0 +1,17 @@
+#
+# MDEV-25925 Warning: Memory not freed: 32 on INSERT DELAYED
+#
+SET sql_mode='TRADITIONAL';
+CREATE TABLE t1 (c BLOB) ENGINE=MyISAM;
+INSERT DELAYED INTO t1 VALUES (''||'');
+ERROR 22007: Truncated incorrect DOUBLE value: ''
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+#
+# MDEV-24467 Memory not freed after failed INSERT DELAYED
+#
+CREATE TABLE t1 (a VARCHAR(1)) ENGINE=MyISAM;
+ALTER TABLE t1 ADD b BLOB DEFAULT 'x';
+INSERT DELAYED INTO t1 (a) VALUES ('foo');
+ERROR 22001: Data too long for column 'a' at row 1
+DROP TABLE t1;
diff --git a/mysql-test/main/delayed_blob.test b/mysql-test/main/delayed_blob.test
new file mode 100644
index 00000000000..bf3e01a8825
--- /dev/null
+++ b/mysql-test/main/delayed_blob.test
@@ -0,0 +1,21 @@
+--echo #
+--echo # MDEV-25925 Warning: Memory not freed: 32 on INSERT DELAYED
+--echo #
+
+SET sql_mode='TRADITIONAL';
+CREATE TABLE t1 (c BLOB) ENGINE=MyISAM;
+--error ER_TRUNCATED_WRONG_VALUE
+INSERT DELAYED INTO t1 VALUES (''||'');
+DROP TABLE t1;
+SET sql_mode=DEFAULT;
+
+
+--echo #
+--echo # MDEV-24467 Memory not freed after failed INSERT DELAYED
+--echo #
+
+CREATE TABLE t1 (a VARCHAR(1)) ENGINE=MyISAM;
+ALTER TABLE t1 ADD b BLOB DEFAULT 'x';
+--error ER_DATA_TOO_LONG
+INSERT DELAYED INTO t1 (a) VALUES ('foo');
+DROP TABLE t1;
diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result
index a1522c473d3..d50a77544f3 100644
--- a/mysql-test/main/func_str.result
+++ b/mysql-test/main/func_str.result
@@ -5014,6 +5014,18 @@ DROP TABLE t1;
# End of 10.1 tests
#
#
+# Start of 10.2 tests
+#
+#
+# MDEV-24742 Server crashes in Charset::numchars / String::numchars
+#
+SELECT NULL IN (RIGHT(AES_ENCRYPT('foo','bar'), LAST_INSERT_ID()), 'qux');
+NULL IN (RIGHT(AES_ENCRYPT('foo','bar'), LAST_INSERT_ID()), 'qux')
+NULL
+#
+# End of 10.2 tests
+#
+#
# Start of 10.3 tests
#
#
diff --git a/mysql-test/main/func_str.test b/mysql-test/main/func_str.test
index efde77f21eb..6a9fbc71371 100644
--- a/mysql-test/main/func_str.test
+++ b/mysql-test/main/func_str.test
@@ -1988,6 +1988,22 @@ DROP TABLE t1;
--echo #
+--echo # Start of 10.2 tests
+--echo #
+
+--echo #
+--echo # MDEV-24742 Server crashes in Charset::numchars / String::numchars
+--echo #
+
+SELECT NULL IN (RIGHT(AES_ENCRYPT('foo','bar'), LAST_INSERT_ID()), 'qux');
+
+
+--echo #
+--echo # End of 10.2 tests
+--echo #
+
+
+--echo #
--echo # Start of 10.3 tests
--echo #
diff --git a/mysql-test/main/invisible_field.result b/mysql-test/main/invisible_field.result
index 9b42b043ec6..081c1ada1ee 100644
--- a/mysql-test/main/invisible_field.result
+++ b/mysql-test/main/invisible_field.result
@@ -538,7 +538,7 @@ a b
insert into t2 values(1);
select a,b from t2;
a b
-NULL 1
+12 1
drop table t1,t2;
create table t1 (a int invisible, b int, c int);
create table t2 (a int, b int, d int);
@@ -627,3 +627,18 @@ drop table t1;
create table t1 (a int, b int invisible);
insert delayed into t1 values (1);
drop table t1;
+#
+# MDEV-25891 Computed default for INVISIBLE column is ignored in INSERT
+#
+create table t1(
+a int,
+x int default (a),
+y int default (a) invisible,
+z int default (33) invisible);
+insert into t1 values (1, default);
+insert into t1 (a) values (2);
+select a, x, y, z from t1;
+a x y z
+1 1 1 33
+2 2 2 33
+drop table t1;
diff --git a/mysql-test/main/invisible_field.test b/mysql-test/main/invisible_field.test
index 7a48347ec29..558ca7aa3a2 100644
--- a/mysql-test/main/invisible_field.test
+++ b/mysql-test/main/invisible_field.test
@@ -279,3 +279,16 @@ create table t1 (a int, b int invisible);
insert delayed into t1 values (1);
# cleanup
drop table t1;
+
+--echo #
+--echo # MDEV-25891 Computed default for INVISIBLE column is ignored in INSERT
+--echo #
+create table t1(
+ a int,
+ x int default (a),
+ y int default (a) invisible,
+ z int default (33) invisible);
+insert into t1 values (1, default);
+insert into t1 (a) values (2);
+select a, x, y, z from t1;
+drop table t1;
diff --git a/mysql-test/main/multi_update.result b/mysql-test/main/multi_update.result
index 4001a47ecd4..3ec9ea0caa5 100644
--- a/mysql-test/main/multi_update.result
+++ b/mysql-test/main/multi_update.result
@@ -1151,3 +1151,13 @@ b
1
3
drop tables t1, t2;
+#
+# MDEV-22464 Server crash on UPDATE with nested subquery
+#
+create table t1 (a int) ;
+insert into t1 (a) values (1),(2),(3) ;
+select a from t1 where a= (select 2 from t1 having (a = 3));
+ERROR 21000: Subquery returns more than 1 row
+update t1 set a= (select 2 from t1 having (a = 3));
+ERROR 21000: Subquery returns more than 1 row
+drop tables t1;
diff --git a/mysql-test/main/multi_update.test b/mysql-test/main/multi_update.test
index 84f06a7c165..3ee36f97fc5 100644
--- a/mysql-test/main/multi_update.test
+++ b/mysql-test/main/multi_update.test
@@ -1087,3 +1087,14 @@ update t1 left join t2 on a = b set b= 3 order by b;
select * from t2;
drop tables t1, t2;
+
+--echo #
+--echo # MDEV-22464 Server crash on UPDATE with nested subquery
+--echo #
+create table t1 (a int) ;
+insert into t1 (a) values (1),(2),(3) ;
+--error ER_SUBQUERY_NO_1_ROW
+select a from t1 where a= (select 2 from t1 having (a = 3));
+--error ER_SUBQUERY_NO_1_ROW
+update t1 set a= (select 2 from t1 having (a = 3));
+drop tables t1;
diff --git a/mysql-test/main/mysql_binary_zero_insert.result b/mysql-test/main/mysql_binary_zero_insert.result
new file mode 100644
index 00000000000..0bed7487b3e
--- /dev/null
+++ b/mysql-test/main/mysql_binary_zero_insert.result
@@ -0,0 +1,54 @@
+# Note: This test assumes NO_BACKSLASH_ESCAPES is not set in SQL_MODE.
+##############################
+# Setup
+##############################
+#
+# Saving old state
+#
+set @old_sql_mode= @@global.SQL_MODE;
+set @@global.SQL_MODE= "";
+#
+# Create table for data entry
+#
+CREATE TABLE tb (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, PRIMARY KEY (`id`)) AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
+RESET MASTER;
+##############################
+# Test Case
+##############################
+#
+# \0 (0x5c00 in binary) should be allowed in data strings if
+# --binary-mode is enabled.
+#
+FOUND 10 /\x5c\x00/ in binary_zero_inserts.sql
+# MYSQL --binary-mode test < MYSQL_TMP_DIR/binary_zero_inserts.sql
+#
+# Ensure a row exists from each insert statement with a \0
+#
+SELECT COUNT(*)=8 from tb;
+COUNT(*)=8
+1
+#
+# Ensure that the binary zero was parsed and exists in the row data
+# Note: We only look for 00 because the 5c only served as an escape
+# in parsing.
+#
+# MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql
+FOUND 10 /00/ in dump.sql
+#
+# Ensure data consistency on mysqlbinlog replay
+#
+FLUSH LOGS;
+# MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > MYSQL_TMP_DIR/binlog_zeros.sql
+FOUND 10 /\x5c\x00/ in binlog_zeros.sql
+# MYSQL --binary-mode test < MYSQL_TMP_DIR/binlog_zeros.sql
+# Table checksum is equivalent before and after binlog replay
+#
+# A \0 should still be treated as end-of-query in binary mode.
+#
+# MYSQL --binary-mode -B test < MYSQL_TMP_DIR/binary_zero_eoq.sql
+##############################
+# Cleanup
+##############################
+SET @@global.sql_mode= @old_sql_mode;
+drop table tb;
+RESET MASTER;
diff --git a/mysql-test/main/mysql_binary_zero_insert.test b/mysql-test/main/mysql_binary_zero_insert.test
new file mode 100644
index 00000000000..b327c8a4d1e
--- /dev/null
+++ b/mysql-test/main/mysql_binary_zero_insert.test
@@ -0,0 +1,170 @@
+#
+# Purpose:
+# This test ensures that the mysql client is able to properly handle the
+# binary data sequence 0x5c00, i.e. the null-terminating character \0, in a
+# string when --binary-mode is enabled. Specifically, this sequence is valid to
+# appear anywhere within a binary data string, and it should not end the string
+# or SQL command. Additionally, \0 outside of a string should still end the
+# query.
+#
+# Methodology:
+# This test initially inserts data with binary strings containing \0. To
+# ensure the mysql client is able to process this data correctly, perl is used
+# to create a SQL file that contains \0 in strings, and this file is used as
+# input into the client. The row data is then validated by searching for binary
+# zeros in mysqldump output.
+#
+#
+# References:
+# MDEV-25444: mysql --binary-mode is not able to replay some mysqlbinlog
+# outputs
+
+--echo # Note: This test assumes NO_BACKSLASH_ESCAPES is not set in SQL_MODE.
+
+--source include/have_log_bin.inc
+
+--echo ##############################
+--echo # Setup
+--echo ##############################
+
+--echo #
+--echo # Saving old state
+--echo #
+set @old_sql_mode= @@global.SQL_MODE;
+set @@global.SQL_MODE= "";
+
+--echo #
+--echo # Create table for data entry
+--echo #
+CREATE TABLE tb (`id` int(11) NOT NULL AUTO_INCREMENT,`cb` longblob DEFAULT NULL, PRIMARY KEY (`id`)) AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
+
+# Will replay binlog later and we don't want to recreate the table
+RESET MASTER;
+
+
+--echo ##############################
+--echo # Test Case
+--echo ##############################
+
+--echo #
+--echo # \0 (0x5c00 in binary) should be allowed in data strings if
+--echo # --binary-mode is enabled.
+--echo #
+--perl
+ my $dir= $ENV{'MYSQL_TMP_DIR'};
+ open (my $FILE, '>', "$dir/binary_zero_inserts.sql") or die "open(): $!";
+
+ print $FILE "TRUNCATE TABLE tb;\n";
+
+ # INSERT INTO tb(cb) VALUES(_binary '\0');
+ print $FILE "INSERT INTO tb(cb) VALUES (_binary '";
+ print $FILE pack "H*","5c00";
+ print $FILE "');\n";
+
+ # INSERT INTO tb(cb) VALUES(_binary '\0A');
+ print $FILE "INSERT INTO tb(cb) VALUES (_binary '";
+ print $FILE pack "H*","5c0041";
+ print $FILE "');\n";
+
+ # INSERT INTO tb(cb) VALUES(_binary 'A\0');
+ print $FILE "INSERT INTO tb(cb) VALUES (_binary '";
+ print $FILE pack "H*","415c00";
+ print $FILE "');\n";
+
+ # INSERT INTO tb(cb) VALUES(_binary 'A\0B');
+ print $FILE "INSERT INTO tb(cb) VALUES (_binary '";
+ print $FILE pack "H*","415c0042";
+ print $FILE "');\n";
+
+ # INSERT INTO tb(cb) VALUES(_binary '\0A\0');
+ print $FILE "INSERT INTO tb(cb) VALUES (_binary '";
+ print $FILE pack "H*","5c00415c00";
+ print $FILE "');\n";
+
+ # INSERT INTO tb(cb) VALUES(_binary '\\\0');
+ print $FILE "INSERT INTO tb(cb) VALUES (_binary '";
+ print $FILE pack "H*","5c5c5c00";
+ print $FILE "');\n";
+
+ # INSERT INTO tb(cb) VALUES(_binary '\0\0');
+ print $FILE "INSERT INTO tb(cb) VALUES (_binary '";
+ print $FILE pack "H*","5c005c00";
+ print $FILE "');\n";
+
+ # INSERT INTO tb(cb) VALUES(_binary '\\0');
+ print $FILE "INSERT INTO tb(cb) VALUES (_binary '";
+ print $FILE pack "H*","5c5c00";
+ print $FILE "');\n";
+
+ close ($FILE);
+EOF
+--let SEARCH_PATTERN= \x5c\x00
+--let SEARCH_FILE= $MYSQL_TMP_DIR/binary_zero_inserts.sql
+--source include/search_pattern_in_file.inc
+--echo # MYSQL --binary-mode test < MYSQL_TMP_DIR/binary_zero_inserts.sql
+--exec $MYSQL --binary-mode test < $MYSQL_TMP_DIR/binary_zero_inserts.sql
+
+--echo #
+--echo # Ensure a row exists from each insert statement with a \0
+--echo #
+SELECT COUNT(*)=8 from tb;
+
+--echo #
+--echo # Ensure that the binary zero was parsed and exists in the row data
+--echo # Note: We only look for 00 because the 5c only served as an escape
+--echo # in parsing.
+--echo #
+--echo # MYSQL_DUMP test tb --hex-blob | grep INSERT > MYSQL_TMP_DIR/dump.sql
+--exec $MYSQL_DUMP test tb --hex-blob | grep INSERT > $MYSQL_TMP_DIR/dump.sql
+--let SEARCH_PATTERN= 00
+--let SEARCH_FILE= $MYSQL_TMP_DIR/dump.sql
+--source include/search_pattern_in_file.inc
+
+--echo #
+--echo # Ensure data consistency on mysqlbinlog replay
+--echo #
+--let $good_checksum= `CHECKSUM TABLE tb`
+let $MYSQLD_DATADIR= `SELECT @@datadir`;
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+FLUSH LOGS;
+--echo # MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > MYSQL_TMP_DIR/binlog_zeros.sql
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQL_TMP_DIR/binlog_zeros.sql
+--let SEARCH_PATTERN= \x5c\x00
+--let SEARCH_FILE= $MYSQL_TMP_DIR/binlog_zeros.sql
+--source include/search_pattern_in_file.inc
+--echo # MYSQL --binary-mode test < MYSQL_TMP_DIR/binlog_zeros.sql
+--exec $MYSQL --binary-mode test < $MYSQL_TMP_DIR/binlog_zeros.sql
+if ($good_checksum != `CHECKSUM TABLE tb`)
+{
+ die "Blob with binary zero data changed after binary log replay";
+}
+--echo # Table checksum is equivalent before and after binlog replay
+
+--echo #
+--echo # A \0 should still be treated as end-of-query in binary mode.
+--echo #
+--perl
+ my $dir= $ENV{'MYSQL_TMP_DIR'};
+ open (my $FILE, '>', "$dir/binary_zero_eoq.sql") or die "open(): $!";
+
+ # INSERT INTO tb(cb) VALUES(_binary 'text')\0
+ print $FILE "INSERT INTO tb(cb) VALUES (_binary 'text')";
+ print $FILE pack "H*","5c00";
+
+ close ($FILE);
+EOF
+--echo # MYSQL --binary-mode -B test < MYSQL_TMP_DIR/binary_zero_eoq.sql
+--exec $MYSQL --binary-mode -B test < $MYSQL_TMP_DIR/binary_zero_eoq.sql
+
+
+--echo ##############################
+--echo # Cleanup
+--echo ##############################
+
+--remove_file $MYSQL_TMP_DIR/binary_zero_inserts.sql
+--remove_file $MYSQL_TMP_DIR/binary_zero_eoq.sql
+--remove_file $MYSQL_TMP_DIR/binlog_zeros.sql
+--remove_file $MYSQL_TMP_DIR/dump.sql
+SET @@global.sql_mode= @old_sql_mode;
+drop table tb;
+RESET MASTER;
diff --git a/mysql-test/suite/innodb/r/mdev-14846.result b/mysql-test/suite/innodb/r/mdev-14846.result
new file mode 100644
index 00000000000..219bd718feb
--- /dev/null
+++ b/mysql-test/suite/innodb/r/mdev-14846.result
@@ -0,0 +1,52 @@
+CREATE TABLE t1 (
+pk INT,
+f1 VARCHAR(10) NOT NULL,
+f2 VARCHAR(10) NULL,
+f3 INT UNSIGNED NULL,
+KEY (f1),
+PRIMARY KEY (pk)
+) ENGINE=InnoDB;
+CREATE OR REPLACE ALGORITHM=MERGE VIEW v4 AS SELECT * FROM t1;
+INSERT INTO t1 VALUES (1,'k','g',6),(2,'y','r',0),(3,'t','q',1),(4,'a','r',NULL),(5,'z','t',NULL);
+CREATE TABLE t2 (f VARCHAR(10) NULL) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (NULL),('g'),('e'),('g');
+CREATE TABLE t3 (
+f1 VARCHAR(10) NOT NULL,
+f2 VARCHAR(10) NULL,
+f3 INT UNSIGNED NULL
+) ENGINE=InnoDB;
+INSERT INTO t3 VALUES ('k','n',9),('y','b',8),('m','w',6);
+CREATE TABLE t4 (f INT NULL) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (8),(9);
+UPDATE t1 SET t1.pk = -109 WHERE t1.f1 IN ( SELECT 'a' FROM t4 WHERE f >= 1 );
+SET DEBUG_SYNC='now SIGNAL con1_dml';
+connect con1,localhost,root,,test;
+SET DEBUG_SYNC='now WAIT_FOR con1_dml';
+begin;
+SELECT * FROM t1 for update;
+pk f1 f2 f3
+-109 a r NULL
+1 k g 6
+2 y r 0
+3 t q 1
+5 z t NULL
+SET DEBUG_SYNC='now SIGNAL default_dml';
+connection default;
+SET DEBUG_SYNC='now WAIT_FOR default_dml';
+UPDATE t3 AS alias1 LEFT JOIN t3 AS alias2 ON ( alias1.f1 <> alias1.f2 ) SET alias1.f3 = 59 WHERE ( EXISTS ( SELECT t1.f3 FROM t1 WHERE t1.f1 = alias1.f1 ) ) OR alias2.f1 = 'h';
+connect con2,localhost,root,,test;
+set debug_sync='now WAIT_FOR default_dml';
+SET DEBUG_SYNC='now SIGNAL con1_dml2';
+disconnect con2;
+connection con1;
+SET DEBUG_SYNC='now WAIT_FOR con1_dml2';
+UPDATE v4, t1 SET t1.pk = 76 WHERE t1.f2 IN ( SELECT t2.f FROM t2 INNER JOIN t3 );
+connection default;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+connection con1;
+COMMIT;
+disconnect con1;
+connection default;
+DROP VIEW v4;
+DROP TABLE t1, t2, t3, t4;
+set debug_sync= reset;
diff --git a/mysql-test/suite/innodb/t/mdev-14846.opt b/mysql-test/suite/innodb/t/mdev-14846.opt
new file mode 100644
index 00000000000..c8fe0561390
--- /dev/null
+++ b/mysql-test/suite/innodb/t/mdev-14846.opt
@@ -0,0 +1 @@
+--loose-innodb_lock_waits
diff --git a/mysql-test/suite/innodb/t/mdev-14846.test b/mysql-test/suite/innodb/t/mdev-14846.test
new file mode 100644
index 00000000000..adcefecd52f
--- /dev/null
+++ b/mysql-test/suite/innodb/t/mdev-14846.test
@@ -0,0 +1,70 @@
+--source include/have_innodb.inc
+--source include/count_sessions.inc
+--source include/have_debug_sync.inc
+
+CREATE TABLE t1 (
+ pk INT,
+ f1 VARCHAR(10) NOT NULL,
+ f2 VARCHAR(10) NULL,
+ f3 INT UNSIGNED NULL,
+ KEY (f1),
+ PRIMARY KEY (pk)
+) ENGINE=InnoDB;
+
+CREATE OR REPLACE ALGORITHM=MERGE VIEW v4 AS SELECT * FROM t1;
+INSERT INTO t1 VALUES (1,'k','g',6),(2,'y','r',0),(3,'t','q',1),(4,'a','r',NULL),(5,'z','t',NULL);
+
+CREATE TABLE t2 (f VARCHAR(10) NULL) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (NULL),('g'),('e'),('g');
+
+CREATE TABLE t3 (
+ f1 VARCHAR(10) NOT NULL,
+ f2 VARCHAR(10) NULL,
+ f3 INT UNSIGNED NULL
+) ENGINE=InnoDB;
+
+INSERT INTO t3 VALUES ('k','n',9),('y','b',8),('m','w',6);
+
+CREATE TABLE t4 (f INT NULL) ENGINE=InnoDB;
+INSERT INTO t4 VALUES (8),(9);
+UPDATE t1 SET t1.pk = -109 WHERE t1.f1 IN ( SELECT 'a' FROM t4 WHERE f >= 1 );
+SET DEBUG_SYNC='now SIGNAL con1_dml';
+
+--connect (con1,localhost,root,,test)
+SET DEBUG_SYNC='now WAIT_FOR con1_dml';
+begin;
+SELECT * FROM t1 for update; # Holds x lock of all records in the table t1
+SET DEBUG_SYNC='now SIGNAL default_dml';
+
+--connection default
+SET DEBUG_SYNC='now WAIT_FOR default_dml';
+--send UPDATE t3 AS alias1 LEFT JOIN t3 AS alias2 ON ( alias1.f1 <> alias1.f2 ) SET alias1.f3 = 59 WHERE ( EXISTS ( SELECT t1.f3 FROM t1 WHERE t1.f1 = alias1.f1 ) ) OR alias2.f1 = 'h'
+# It holds the lock of all record in t3 and tries to acquire record lock for the table t1.
+
+--connect (con2,localhost,root,,test)
+set debug_sync='now WAIT_FOR default_dml';
+let $wait_condition=
+select count(*) > 0 from information_schema.innodb_lock_waits;
+--source include/wait_condition.inc
+SET DEBUG_SYNC='now SIGNAL con1_dml2';
+disconnect con2;
+
+# Cleanup
+--connection con1
+SET DEBUG_SYNC='now WAIT_FOR con1_dml2';
+UPDATE v4, t1 SET t1.pk = 76 WHERE t1.f2 IN ( SELECT t2.f FROM t2 INNER JOIN t3 );
+# It holds the record lock on table t1 and tries to acquire record lock on t3.
+# leads to deadlock (con1 trx is waiting for default trx and vice versa)
+
+--connection default
+--error ER_LOCK_DEADLOCK
+--reap
+
+connection con1;
+COMMIT;
+disconnect con1;
+
+--connection default
+DROP VIEW v4;
+DROP TABLE t1, t2, t3, t4;
+set debug_sync= reset;
diff --git a/mysql-test/suite/plugins/r/feedback_plugin_send.result b/mysql-test/suite/plugins/r/feedback_plugin_send.result
index 5a48c703ec4..69046e16dd9 100644
--- a/mysql-test/suite/plugins/r/feedback_plugin_send.result
+++ b/mysql-test/suite/plugins/r/feedback_plugin_send.result
@@ -24,7 +24,23 @@ VARIABLE_VALUE>0 VARIABLE_NAME
1 Collation used utf8mb4_bin
1 Collation used utf8_bin
1 Collation used utf8_general_ci
+prepare stmt from "SELECT VARIABLE_VALUE>0, VARIABLE_NAME FROM INFORMATION_SCHEMA.FEEDBACK WHERE VARIABLE_NAME LIKE 'Collation used %' ORDER BY VARIABLE_NAME";
+execute stmt;
+VARIABLE_VALUE>0 VARIABLE_NAME
+1 Collation used binary
+1 Collation used latin1_swedish_ci
+1 Collation used utf8mb4_bin
+1 Collation used utf8_bin
+1 Collation used utf8_general_ci
+execute stmt;
+VARIABLE_VALUE>0 VARIABLE_NAME
+1 Collation used binary
+1 Collation used latin1_swedish_ci
+1 Collation used utf8mb4_bin
+1 Collation used utf8_bin
+1 Collation used utf8_general_ci
+deallocate prepare stmt;
set global sql_mode=ONLY_FULL_GROUP_BY;
# restart
-6: feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent
-6: feedback plugin: server replied 'ok'
+feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent
+feedback plugin: server replied 'ok'
diff --git a/mysql-test/suite/plugins/t/feedback_plugin_send.test b/mysql-test/suite/plugins/t/feedback_plugin_send.test
index b28f9d4cb38..0ea1814ec29 100644
--- a/mysql-test/suite/plugins/t/feedback_plugin_send.test
+++ b/mysql-test/suite/plugins/t/feedback_plugin_send.test
@@ -38,6 +38,6 @@ perl;
while ($_=<LOG>) {
$logg{$&}++ if /feedback plugin:.*/;
}
- print "$logg{$_}: $_\n" for sort keys %logg;
+ print "$_\n" for sort keys %logg;
close LOG;
EOF
diff --git a/mysql-test/suite/versioning/r/alter.result b/mysql-test/suite/versioning/r/alter.result
index b2dbbba7027..c3feab166c9 100644
--- a/mysql-test/suite/versioning/r/alter.result
+++ b/mysql-test/suite/versioning/r/alter.result
@@ -762,3 +762,22 @@ delete from t1;
set system_versioning_alter_history= keep;
alter ignore table t1 drop pk;
drop table t1;
+#
+# MDEV-22660 SIGSEGV on adding system versioning and modifying system column
+#
+create or replace table t1 (a int);
+alter table t1
+add row_start timestamp(6) as row start,
+add row_end timestamp(6) as row end,
+add period for system_time(row_start, row_end),
+with system versioning,
+modify row_end varchar(8);
+ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `row_start` and `row_end`
+alter table t1
+add row_start timestamp(6) as row start,
+add row_end timestamp(6) as row end,
+add period for system_time(row_start, row_end),
+with system versioning,
+modify row_start varchar(8);
+ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `row_start` and `row_end`
+drop table t1;
diff --git a/mysql-test/suite/versioning/t/alter.test b/mysql-test/suite/versioning/t/alter.test
index 16f391b1454..f826ba470f1 100644
--- a/mysql-test/suite/versioning/t/alter.test
+++ b/mysql-test/suite/versioning/t/alter.test
@@ -653,3 +653,25 @@ set system_versioning_alter_history= keep;
alter ignore table t1 drop pk;
# cleanup
drop table t1;
+
+
+--echo #
+--echo # MDEV-22660 SIGSEGV on adding system versioning and modifying system column
+--echo #
+create or replace table t1 (a int);
+--error ER_VERS_PERIOD_COLUMNS
+alter table t1
+ add row_start timestamp(6) as row start,
+ add row_end timestamp(6) as row end,
+ add period for system_time(row_start, row_end),
+ with system versioning,
+ modify row_end varchar(8);
+--error ER_VERS_PERIOD_COLUMNS
+alter table t1
+ add row_start timestamp(6) as row start,
+ add row_end timestamp(6) as row end,
+ add period for system_time(row_start, row_end),
+ with system versioning,
+ modify row_start varchar(8);
+# cleanup
+drop table t1;
diff --git a/mysys/my_context.c b/mysys/my_context.c
index 5423f59d19b..4153927d335 100644
--- a/mysys/my_context.c
+++ b/mysys/my_context.c
@@ -29,6 +29,10 @@
#endif
#ifdef MY_CONTEXT_USE_UCONTEXT
+#ifdef __APPLE__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
/*
The makecontext() only allows to pass integers into the created context :-(
We want to pass pointers, so we do it this kinda hackish way.
@@ -154,6 +158,9 @@ my_context_destroy(struct my_context *c)
DBUG_FREE_CODE_STATE(&c->dbug_state);
}
+#ifdef __APPLE__
+#pragma GCC diagnostic pop
+#endif
#endif /* MY_CONTEXT_USE_UCONTEXT */
diff --git a/sql/field.cc b/sql/field.cc
index 8b82077f452..2226137b043 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2394,7 +2394,7 @@ Field *Field::make_new_field(MEM_ROOT *root, TABLE *new_table,
tmp->unireg_check= Field::NONE;
tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG |
- VERS_SYS_START_FLAG | VERS_SYS_END_FLAG |
+ VERS_ROW_START | VERS_ROW_END |
VERS_UPDATE_UNVERSIONED_FLAG);
tmp->reset_fields();
tmp->invisible= VISIBLE;
diff --git a/sql/field.h b/sql/field.h
index 5c2ba4c5c84..a51f279e59b 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1600,7 +1600,7 @@ public:
bool vers_sys_field() const
{
- return flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG);
+ return flags & (VERS_ROW_START | VERS_ROW_END);
}
bool vers_update_unversioned() const
@@ -4805,7 +4805,7 @@ public:
}
bool vers_sys_field() const
{
- return flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG);
+ return flags & (VERS_ROW_START | VERS_ROW_END);
}
void create_length_to_internal_length_bit();
void create_length_to_internal_length_newdecimal();
@@ -5175,6 +5175,15 @@ public:
}
/* Used to make a clone of this object for ALTER/CREATE TABLE */
Create_field *clone(MEM_ROOT *mem_root) const;
+
+ bool is_some_bigint() const
+ {
+ return type_handler() == &type_handler_longlong ||
+ type_handler() == &type_handler_vers_trx_id;
+ }
+
+ bool vers_check_timestamp(const Lex_table_name &table_name) const;
+ bool vers_check_bigint(const Lex_table_name &table_name) const;
};
diff --git a/sql/handler.cc b/sql/handler.cc
index 757fa95a9a3..4e891f5d640 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -7438,11 +7438,11 @@ bool Vers_parse_info::is_end(const char *name) const
}
bool Vers_parse_info::is_start(const Create_field &f) const
{
- return f.flags & VERS_SYS_START_FLAG;
+ return f.flags & VERS_ROW_START;
}
bool Vers_parse_info::is_end(const Create_field &f) const
{
- return f.flags & VERS_SYS_END_FLAG;
+ return f.flags & VERS_ROW_END;
}
static Create_field *vers_init_sys_field(THD *thd, const char *field_name, int flags, bool integer)
@@ -7502,8 +7502,8 @@ bool Vers_parse_info::fix_implicit(THD *thd, Alter_info *alter_info)
period= start_end_t(default_start, default_end);
as_row= period;
- if (vers_create_sys_field(thd, default_start, alter_info, VERS_SYS_START_FLAG) ||
- vers_create_sys_field(thd, default_end, alter_info, VERS_SYS_END_FLAG))
+ if (vers_create_sys_field(thd, default_start, alter_info, VERS_ROW_START) ||
+ vers_create_sys_field(thd, default_end, alter_info, VERS_ROW_END))
{
return true;
}
@@ -7662,7 +7662,7 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info,
return true;
}
my_error(ER_VERS_DUPLICATE_ROW_START_END, MYF(0),
- f->flags & VERS_SYS_START_FLAG ? "START" : "END", f->field_name.str);
+ f->flags & VERS_ROW_START ? "START" : "END", f->field_name.str);
return true;
}
}
@@ -7767,13 +7767,13 @@ Vers_parse_info::fix_create_like(Alter_info &alter_info, HA_CREATE_INFO &create_
while ((f= it++))
{
- if (f->flags & VERS_SYS_START_FLAG)
+ if (f->flags & VERS_ROW_START)
{
f_start= f;
if (f_end)
break;
}
- else if (f->flags & VERS_SYS_END_FLAG)
+ else if (f->flags & VERS_ROW_END)
{
f_end= f;
if (f_start)
@@ -7835,37 +7835,31 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name,
return false;
}
-static bool is_versioning_timestamp(const Create_field *f)
-{
- return f->type_handler() == &type_handler_timestamp2 &&
- f->length == MAX_DATETIME_FULL_WIDTH;
-}
-static bool is_some_bigint(const Create_field *f)
+bool Create_field::vers_check_timestamp(const Lex_table_name &table_name) const
{
- return f->type_handler() == &type_handler_longlong ||
- f->type_handler() == &type_handler_vers_trx_id;
-}
-
-static bool is_versioning_bigint(const Create_field *f)
-{
- return is_some_bigint(f) && f->flags & UNSIGNED_FLAG &&
- f->length == MY_INT64_NUM_DECIMAL_DIGITS - 1;
-}
+ if (type_handler() == &type_handler_timestamp2 &&
+ length == MAX_DATETIME_FULL_WIDTH)
+ return false;
-static bool require_timestamp(const Create_field *f, Lex_table_name table_name)
-{
- my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str, "TIMESTAMP(6)",
+ my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), field_name.str, "TIMESTAMP(6)",
table_name.str);
return true;
}
-static bool require_bigint(const Create_field *f, Lex_table_name table_name)
+
+
+bool Create_field::vers_check_bigint(const Lex_table_name &table_name) const
{
- my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str,
+ if (is_some_bigint() && flags & UNSIGNED_FLAG &&
+ length == MY_INT64_NUM_DECIMAL_DIGITS - 1)
+ return false;
+
+ my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), field_name.str,
"BIGINT(20) UNSIGNED", table_name.str);
return true;
}
+
bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
const Lex_table_name &db,
Alter_info *alter_info,
@@ -7880,37 +7874,37 @@ bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
List_iterator<Create_field> it(alter_info->create_list);
while (Create_field *f= it++)
{
- if (!row_start && f->flags & VERS_SYS_START_FLAG)
+ if (!row_start && f->flags & VERS_ROW_START)
row_start= f;
- else if (!row_end && f->flags & VERS_SYS_END_FLAG)
+ else if (!row_end && f->flags & VERS_ROW_END)
row_end= f;
}
- const bool expect_timestamp=
- !can_native || !is_some_bigint(row_start) || !is_some_bigint(row_end);
-
- if (expect_timestamp)
+ if (!row_start || !row_end)
{
- if (!is_versioning_timestamp(row_start))
- return require_timestamp(row_start, table_name);
+ my_error(ER_VERS_PERIOD_COLUMNS, MYF(0), as_row.start.str, as_row.end.str);
+ return true;
+ }
- if (!is_versioning_timestamp(row_end))
- return require_timestamp(row_end, table_name);
+ if (!can_native ||
+ !row_start->is_some_bigint() ||
+ !row_end->is_some_bigint())
+ {
+ if (row_start->vers_check_timestamp(table_name) ||
+ row_end->vers_check_timestamp(table_name))
+ return true;
}
else
{
- if (!is_versioning_bigint(row_start))
- return require_bigint(row_start, table_name);
-
- if (!is_versioning_bigint(row_end))
- return require_bigint(row_end, table_name);
- }
+ if (row_start->vers_check_bigint(table_name) ||
+ row_end->vers_check_bigint(table_name))
+ return true;
- if (is_versioning_bigint(row_start) && is_versioning_bigint(row_end) &&
- !TR_table::use_transaction_registry)
- {
- my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
- return true;
+ if (!TR_table::use_transaction_registry)
+ {
+ my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
+ return true;
+ }
}
return false;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 4f62452aa5a..4e9d9df0990 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -359,6 +359,8 @@ String *Item_aes_crypt::val_str(String *str2)
rkey, AES_KEY_LENGTH / 8, 0, 0))
{
str2->length((uint) aes_length);
+ DBUG_ASSERT(collation.collation == &my_charset_bin);
+ str2->set_charset(&my_charset_bin);
return str2;
}
}
diff --git a/sql/item_vers.cc b/sql/item_vers.cc
index 792c434b8c3..9a594533628 100644
--- a/sql/item_vers.cc
+++ b/sql/item_vers.cc
@@ -30,7 +30,7 @@ bool Item_func_history::val_bool()
{
Item_field *f= static_cast<Item_field *>(args[0]);
DBUG_ASSERT(f->fixed);
- DBUG_ASSERT(f->field->flags & VERS_SYS_END_FLAG);
+ DBUG_ASSERT(f->field->flags & VERS_ROW_END);
return !f->field->is_max();
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index ba1d477882f..ec77366129a 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -8832,7 +8832,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr)
if (global_system_variables.low_priority_updates)
thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY;
- if (ft_boolean_check_syntax_string((uchar*) ft_boolean_syntax))
+ if (ft_boolean_check_syntax_string((uchar*) ft_boolean_syntax,
+ strlen(ft_boolean_syntax),
+ system_charset_info))
{
sql_print_error("Invalid ft-boolean-syntax string: %s",
ft_boolean_syntax);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 88cb16e3e7d..5132b0e2e85 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8869,6 +8869,8 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
if (!thd->is_error())
{
thd->abort_on_warning= FALSE;
+ if (table->default_field && table->update_default_fields(ignore_errors))
+ goto err;
if (table->versioned())
table->vers_update_fields();
if (table->vfield &&
diff --git a/sql/sql_explain.h b/sql/sql_explain.h
index ce3f3ef06e1..6575511bd52 100644
--- a/sql/sql_explain.h
+++ b/sql/sql_explain.h
@@ -121,11 +121,13 @@ public:
*/
enum explain_connection_type connection_type;
+protected:
/*
A node may have children nodes. When a node's explain structure is
created, children nodes may not yet have QPFs. This is why we store ids.
*/
Dynamic_array<int> children;
+public:
void add_child(int select_no)
{
children.append(select_no);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index f34632b3df8..4bf15bfbb9b 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1288,7 +1288,18 @@ values_loop_end:
abort:
#ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED)
+ {
end_delayed_insert(thd);
+ /*
+ In case of an error (e.g. data truncation), the data type specific data
+ in fields (e.g. Field_blob::value) was not taken over
+ by the delayed writer thread. All fields in table_list->table
+ will be freed by free_root() soon. We need to free the specific
+ data before free_root() to avoid a memory leak.
+ */
+ for (Field **ptr= table_list->table->field ; *ptr ; ptr++)
+ (*ptr)->free();
+ }
#endif
if (table != NULL)
table->file->ha_release_auto_increment();
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index c6db441220e..93002677fbd 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -8924,7 +8924,7 @@ bool LEX::last_field_generated_always_as_row_start()
Vers_parse_info &info= vers_get_info();
Lex_ident *p= &info.as_row.start;
return last_field_generated_always_as_row_start_or_end(p, "START",
- VERS_SYS_START_FLAG);
+ VERS_ROW_START);
}
@@ -8933,7 +8933,7 @@ bool LEX::last_field_generated_always_as_row_end()
Vers_parse_info &info= vers_get_info();
Lex_ident *p= &info.as_row.end;
return last_field_generated_always_as_row_start_or_end(p, "END",
- VERS_SYS_END_FLAG);
+ VERS_ROW_END);
}
void st_select_lex_unit::reset_distinct()
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1eb0a492ecd..2010260eaf6 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -4663,7 +4663,8 @@ mysql_select(THD *thd,
bool free_join= 1;
DBUG_ENTER("mysql_select");
- select_lex->context.resolve_in_select_list= TRUE;
+ if (!fields.is_empty())
+ select_lex->context.resolve_in_select_list= true;
JOIN *join;
if (select_lex->join != 0)
{
@@ -20737,26 +20738,33 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
will be re-evaluated again. It could be fixed, but, probably,
it's not worth doing now.
*/
- if (tab->select_cond && !tab->select_cond->val_int())
+ if (tab->select_cond)
{
- /* The condition attached to table tab is false */
- if (tab == join_tab)
- {
- found= 0;
- if (not_exists_opt_is_applicable)
- DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
- }
- else
+ const longlong res= tab->select_cond->val_int();
+ if (join->thd->is_error())
+ DBUG_RETURN(NESTED_LOOP_ERROR);
+
+ if (!res)
{
- /*
- Set a return point if rejected predicate is attached
- not to the last table of the current nest level.
- */
- join->return_tab= tab;
- if (not_exists_opt_is_applicable)
- DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
+ /* The condition attached to table tab is false */
+ if (tab == join_tab)
+ {
+ found= 0;
+ if (not_exists_opt_is_applicable)
+ DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
+ }
else
- DBUG_RETURN(NESTED_LOOP_OK);
+ {
+ /*
+ Set a return point if rejected predicate is attached
+ not to the last table of the current nest level.
+ */
+ join->return_tab= tab;
+ if (not_exists_opt_is_applicable)
+ DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
+ else
+ DBUG_RETURN(NESTED_LOOP_OK);
+ }
}
}
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 31fb2f6a654..40efe1ec550 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2302,11 +2302,11 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
}
else
{
- if (field->flags & VERS_SYS_START_FLAG)
+ if (field->flags & VERS_ROW_START)
{
packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS ROW START"));
}
- else if (field->flags & VERS_SYS_END_FLAG)
+ else if (field->flags & VERS_ROW_END)
{
packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS ROW END"));
}
@@ -6119,7 +6119,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
}
else if (field->flags & VERS_SYSTEM_FIELD)
{
- if (field->flags & VERS_SYS_START_FLAG)
+ if (field->flags & VERS_ROW_START)
{
table->field[21]->store(STRING_WITH_LEN("ROW START"), cs);
buf.set(STRING_WITH_LEN("STORED GENERATED"), cs);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index dbe5ac15172..12e09e7bcb2 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -8280,7 +8280,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
def= new (thd->mem_root) Create_field(thd, field, field);
def->invisible= INVISIBLE_SYSTEM;
alter_info->flags|= ALTER_CHANGE_COLUMN;
- if (field->flags & VERS_SYS_START_FLAG)
+ if (field->flags & VERS_ROW_START)
create_info->vers_info.as_row.start= def->field_name= Vers_parse_info::default_start;
else
create_info->vers_info.as_row.end= def->field_name= Vers_parse_info::default_end;
@@ -8321,9 +8321,9 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
!vers_system_invisible)
{
StringBuffer<NAME_LEN*3> tmp;
- if (!(dropped_sys_vers_fields & VERS_SYS_START_FLAG))
+ if (!(dropped_sys_vers_fields & VERS_ROW_START))
append_drop_column(thd, &tmp, table->vers_start_field());
- if (!(dropped_sys_vers_fields & VERS_SYS_END_FLAG))
+ if (!(dropped_sys_vers_fields & VERS_ROW_END))
append_drop_column(thd, &tmp, table->vers_end_field());
my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr());
goto err;
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index c349a433075..e0a6169df3d 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -7776,7 +7776,7 @@ Field *Type_handler_longlong::
const Column_definition_attributes *attr,
uint32 flags) const
{
- if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG))
+ if (flags & (VERS_ROW_START|VERS_ROW_END))
return new (mem_root)
Field_vers_trx_id(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 14d45d951eb..53a978794f2 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1105,7 +1105,9 @@ static Sys_var_ulong Sys_flush_time(
static bool check_ftb_syntax(sys_var *self, THD *thd, set_var *var)
{
return ft_boolean_check_syntax_string((uchar*)
- (var->save_result.string_value.str));
+ (var->save_result.string_value.str),
+ var->save_result.string_value.length,
+ self->charset(thd));
}
static bool query_cache_flush(sys_var *self, THD *thd, enum_var_type type)
{
diff --git a/sql/table.cc b/sql/table.cc
index 421a728c648..e24309fdd70 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1299,7 +1299,10 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
if (check_vcol_forward_refs(field, field->vcol_info, 0) ||
check_vcol_forward_refs(field, field->check_constraint, 1) ||
check_vcol_forward_refs(field, field->default_value, 0))
+ {
+ *error_reported= true;
goto end;
+ }
}
table->find_constraint_correlated_indexes();
@@ -2359,9 +2362,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (versioned)
{
if (i == vers.start_fieldno)
- flags|= VERS_SYS_START_FLAG;
+ flags|= VERS_ROW_START;
else if (i == vers.end_fieldno)
- flags|= VERS_SYS_END_FLAG;
+ flags|= VERS_ROW_END;
if (flags & VERS_SYSTEM_FIELD)
{
diff --git a/storage/connect/bsonudf.cpp b/storage/connect/bsonudf.cpp
index 0c7112ee15f..771e72b8dbd 100644
--- a/storage/connect/bsonudf.cpp
+++ b/storage/connect/bsonudf.cpp
@@ -12,6 +12,7 @@
#include <mysql.h>
#include <sql_error.h>
#include <stdio.h>
+#include <cassert>
#include "bsonudf.h"
@@ -621,7 +622,7 @@ PVAL BJNX::GetCalcValue(PGLOBAL g, PBVAL bap, int n)
{
// For calculated arrays, a local Value must be used
int lng = 0;
- short type, prec = 0;
+ short type = 0, prec = 0;
bool b = n < Nod - 1;
PVAL valp;
PBVAL vlp, vp;
@@ -690,7 +691,7 @@ PVAL BJNX::GetCalcValue(PGLOBAL g, PBVAL bap, int n)
break;
default:
- break;
+ DBUG_ASSERT(!"Implement new op type support.");
} // endswitch Op
return valp = AllocateValue(g, type, lng, prec);
@@ -4978,7 +4979,7 @@ char *bbin_array_add(UDF_INIT *initid, UDF_ARGS *args, char *result,
uint n = 2;
int* x = GetIntArgPtr(g, args, n);
BJNX bnx(g, NULL, TYPE_STRING);
- PBVAL jarp, top, jvp = NULL;
+ PBVAL jarp = NULL, top = NULL, jvp = NULL;
PBVAL jsp = bnx.MakeValue(args, 0, true, &top);
if (bnx.CheckPath(g, args, jsp, jvp, 2))
@@ -5611,7 +5612,7 @@ char *bbin_object_values(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!bsp) {
if (!CheckMemory(g, initid, args, 1, true, true)) {
BJNX bnx(g);
- PBVAL top, jarp;
+ PBVAL top, jarp = NULL;
PBVAL jvp = bnx.MakeValue(args, 0, true, &top);
if (jvp->Type == TYPE_JOB) {
diff --git a/storage/connect/inihandl.cpp b/storage/connect/inihandl.cpp
index 9270e18721c..de04fa91883 100644
--- a/storage/connect/inihandl.cpp
+++ b/storage/connect/inihandl.cpp
@@ -193,7 +193,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section )
secno++;
}
- for (key = section->key; key; key = key->next)
+ for (key = section->key; key; key = key->next) {
if (key->name[0]) {
fprintf(file, "%s", SVP(key->name));
@@ -201,9 +201,9 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section )
fprintf(file, "=%s", SVP(key->value));
fprintf(file, "\n");
- } // endif key->name
-
- } // endfor section
+ } // endif key->name
+ }
+ } // endfor section
} // end of PROFILE_Save
diff --git a/storage/connect/tabbson.cpp b/storage/connect/tabbson.cpp
index 3b1f1c84d1a..a7c561318c7 100644
--- a/storage/connect/tabbson.cpp
+++ b/storage/connect/tabbson.cpp
@@ -871,7 +871,7 @@ PBVAL BCUTIL::MakeBson(PGLOBAL g, PBVAL jsp, int n)
/***********************************************************************/
PBVAL BCUTIL::GetRowValue(PGLOBAL g, PBVAL row, int i)
{
- int nod = Cp->Nod, n = nod - 1;
+ int nod = Cp->Nod;
JNODE *nodes = Cp->Nodes;
PBVAL arp;
PBVAL bvp = NULL;
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index b2e8a15fbd3..d354fd93209 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -795,13 +795,9 @@ loop:
/** Flush the recently written changes to the log file.
and invoke log_mutex_enter(). */
-static
-void
-log_write_flush_to_disk_low()
+static void log_write_flush_to_disk_low()
{
- /* FIXME: This is not holding log_sys.mutex while
- calling os_event_set()! */
- ut_a(log_sys.n_pending_flushes == 1); /* No other threads here */
+ ut_a(log_sys.n_pending_flushes);
bool do_flush = srv_file_flush_method != SRV_O_DSYNC;
@@ -809,7 +805,6 @@ log_write_flush_to_disk_low()
fil_flush(SRV_LOG_SPACE_FIRST_ID);
}
-
log_mutex_enter();
if (do_flush) {
log_sys.flushed_to_disk_lsn = log_sys.current_flush_lsn;
@@ -1123,7 +1118,7 @@ ATTRIBUTE_COLD void log_write_and_flush()
/* Code adapted from log_write_flush_to_disk_low() */
- ut_a(log_sys.n_pending_flushes == 1); /* No other threads here */
+ ut_a(log_sys.n_pending_flushes);
if (srv_file_flush_method != SRV_O_DSYNC)
fil_flush(SRV_LOG_SPACE_FIRST_ID);
diff --git a/storage/myisam/ft_parser.c b/storage/myisam/ft_parser.c
index b400990d934..bc50301fab2 100644
--- a/storage/myisam/ft_parser.c
+++ b/storage/myisam/ft_parser.c
@@ -78,18 +78,25 @@ FT_WORD * ft_linearize(TREE *wtree, MEM_ROOT *mem_root)
DBUG_RETURN(wlist);
}
-my_bool ft_boolean_check_syntax_string(const uchar *str)
+my_bool ft_boolean_check_syntax_string(const uchar *str, size_t length,
+ CHARSET_INFO *cs)
{
uint i, j;
+ if (cs->mbminlen != 1)
+ {
+ DBUG_ASSERT(0);
+ return 1;
+ }
+
if (!str ||
- (strlen((char*) str)+1 != sizeof(DEFAULT_FTB_SYNTAX)) ||
+ (length + 1 != sizeof(DEFAULT_FTB_SYNTAX)) ||
(str[0] != ' ' && str[1] != ' '))
return 1;
for (i=0; i<sizeof(DEFAULT_FTB_SYNTAX); i++)
{
/* limiting to 7-bit ascii only */
- if ((unsigned char)(str[i]) > 127 || my_isalnum(default_charset_info, str[i]))
+ if ((unsigned char)(str[i]) > 127 || my_isalnum(cs, str[i]))
return 1;
for (j=0; j<i; j++)
if (str[i] == str[j] && (i != 11 || j != 10))