Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä 2021-10-13 12:03:32 +03:00
commit a736a3174a
54 changed files with 754 additions and 121 deletions

3
.gitignore vendored
View File

@ -373,6 +373,7 @@ x86/
build/ build/
bld/ bld/
[Bb]in/ [Bb]in/
/cmake-build-debug/
[Oo]bj/ [Oo]bj/
# Roslyn cache directories # Roslyn cache directories
@ -555,7 +556,7 @@ compile_commands.json
.vscode/ .vscode/
# Clion && other JetBrains ides # Clion && other JetBrains ides
.idea /.idea/
.cache/clangd .cache/clangd

View File

@ -1672,11 +1672,14 @@ static struct my_option my_long_options[] =
&opt_default_auth, &opt_default_auth, 0, &opt_default_auth, &opt_default_auth, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"binary-mode", 0, {"binary-mode", 0,
"By default, ASCII '\\0' is disallowed and '\\r\\n' is translated to '\\n'. " "Binary mode allows certain character sequences to be processed as data "
"This switch turns off both features, and also turns off parsing of all client" "that would otherwise be treated with a special meaning by the parser. "
"commands except \\C and DELIMITER, in non-interactive mode (for input " "Specifically, this switch turns off parsing of all client commands except "
"piped to mysql or loaded using the 'source' command). This is necessary " "\\C and DELIMITER in non-interactive mode (i.e., when binary mode is "
"when processing output from mysqlbinlog that may contain blobs.", "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}, &opt_binary_mode, &opt_binary_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"connect-expired-password", 0, {"connect-expired-password", 0,
"Notify the server that this client is prepared to handle expired " "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 // 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 if (*in_string || inchar == 'N') // \N is short for NULL
{ // Don't allow commands in string { // Don't allow commands in string
*out++='\\'; *out++='\\';

View File

@ -90,7 +90,8 @@ void ft_free_stopwords(void);
FT_INFO *ft_init_search(uint,void *, uint, uchar *, size_t, FT_INFO *ft_init_search(uint,void *, uint, uchar *, size_t,
CHARSET_INFO *, uchar *); 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 */ /* Internal symbols for fulltext between maria and MyISAM */

View File

@ -52,6 +52,9 @@ struct my_context {
#ifdef MY_CONTEXT_USE_UCONTEXT #ifdef MY_CONTEXT_USE_UCONTEXT
#if defined(__APPLE__) && !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE
#endif
#include <ucontext.h> #include <ucontext.h>
struct my_context { struct my_context {

View File

@ -159,7 +159,7 @@
# if defined(__i386__) || defined(__ppc__) # if defined(__i386__) || defined(__ppc__)
# define SIZEOF_CHARP 4 # define SIZEOF_CHARP 4
# define SIZEOF_LONG 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_CHARP 8
# define SIZEOF_LONG 8 # define SIZEOF_LONG 8
# else # else

View File

@ -193,13 +193,13 @@ enum enum_indicator_type
#define FIELD_FLAGS_COLUMN_FORMAT_MASK (3U << FIELD_FLAGS_COLUMN_FORMAT) #define FIELD_FLAGS_COLUMN_FORMAT_MASK (3U << FIELD_FLAGS_COLUMN_FORMAT)
#define FIELD_IS_DROPPED (1U << 26) /* Intern: Field is being dropped */ #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` `generated always as row start`
(see II.a SQL Standard) */ (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` `generated always as row end`
(see II.a SQL Standard).*/ (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 #define VERS_UPDATE_UNVERSIONED_FLAG (1 << 29) /* column that doesn't support
system versioning when table system versioning when table
itself supports it*/ itself supports it*/

View File

@ -206,7 +206,14 @@ option\&.
.\" binary-mode option: mysql .\" binary-mode option: mysql
\fB\-\-binary\-mode\fR \fB\-\-binary\-mode\fR
.sp .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 .RE
.sp .sp
.RS 4 .RS 4

View File

@ -8,3 +8,8 @@ character_set_server utf16
SHOW VARIABLES LIKE 'ft_stopword_file'; SHOW VARIABLES LIKE 'ft_stopword_file';
Variable_name Value Variable_name Value
ft_stopword_file (built-in) 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;

View File

@ -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 'collation_server';
SHOW VARIABLES LIKE 'character_set_server'; SHOW VARIABLES LIKE 'character_set_server';
SHOW VARIABLES LIKE 'ft_stopword_file'; 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;

View File

@ -0,0 +1 @@
--character-set-server=utf32,latin1 --collation-server=utf32_general_ci

View File

@ -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;

View File

@ -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;

View File

@ -3387,6 +3387,14 @@ CREATE OR REPLACE TABLE t1(i int);
ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`; ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;
ERROR 42S22: Unknown column 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in 'DEFAULT' ERROR 42S22: Unknown column 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in 'DEFAULT'
DROP TABLE t1; 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 # end of 10.2 test
# #
# MDEV-22703 DEFAULT() on a BLOB column can overwrite the default # MDEV-22703 DEFAULT() on a BLOB column can overwrite the default
@ -3403,3 +3411,4 @@ length(DEFAULT(h))
25 25
INSERT INTO t1 () VALUES (); INSERT INTO t1 () VALUES ();
drop table t1; drop table t1;
# end of 10.3 test

View File

@ -2109,6 +2109,13 @@ CREATE OR REPLACE TABLE t1(i int);
ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`; ALTER TABLE t1 ADD b CHAR(255) DEFAULT `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;
DROP TABLE t1; 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 # end of 10.2 test
--echo # --echo #
@ -2126,3 +2133,5 @@ SELECT DEFAULT(h) FROM t1;
SELECT length(DEFAULT(h)) FROM t1; SELECT length(DEFAULT(h)) FROM t1;
INSERT INTO t1 () VALUES (); INSERT INTO t1 () VALUES ();
drop table t1; drop table t1;
--echo # end of 10.3 test

View File

@ -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'"

View File

@ -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;

View File

@ -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;

View File

@ -5014,6 +5014,18 @@ DROP TABLE t1;
# End of 10.1 tests # 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 # Start of 10.3 tests
# #
# #

View File

@ -1987,6 +1987,22 @@ DROP TABLE t1;
--echo # --echo #
--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 #
--echo # Start of 10.3 tests --echo # Start of 10.3 tests
--echo # --echo #

View File

@ -538,7 +538,7 @@ a b
insert into t2 values(1); insert into t2 values(1);
select a,b from t2; select a,b from t2;
a b a b
NULL 1 12 1
drop table t1,t2; drop table t1,t2;
create table t1 (a int invisible, b int, c int); create table t1 (a int invisible, b int, c int);
create table t2 (a int, b int, d 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); create table t1 (a int, b int invisible);
insert delayed into t1 values (1); insert delayed into t1 values (1);
drop table t1; 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;

View File

@ -279,3 +279,16 @@ create table t1 (a int, b int invisible);
insert delayed into t1 values (1); insert delayed into t1 values (1);
# cleanup # cleanup
drop table t1; 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;

View File

@ -1151,3 +1151,13 @@ b
1 1
3 3
drop tables t1, t2; 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;

View File

@ -1087,3 +1087,14 @@ update t1 left join t2 on a = b set b= 3 order by b;
select * from t2; select * from t2;
drop tables t1, 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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -0,0 +1 @@
--loose-innodb_lock_waits

View File

@ -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;

View File

@ -24,7 +24,23 @@ VARIABLE_VALUE>0 VARIABLE_NAME
1 Collation used utf8mb4_bin 1 Collation used utf8mb4_bin
1 Collation used utf8_bin 1 Collation used utf8_bin
1 Collation used utf8_general_ci 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; set global sql_mode=ONLY_FULL_GROUP_BY;
# restart # restart
6: feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent
6: feedback plugin: server replied 'ok' feedback plugin: server replied 'ok'

View File

@ -38,6 +38,6 @@ perl;
while ($_=<LOG>) { while ($_=<LOG>) {
$logg{$&}++ if /feedback plugin:.*/; $logg{$&}++ if /feedback plugin:.*/;
} }
print "$logg{$_}: $_\n" for sort keys %logg; print "$_\n" for sort keys %logg;
close LOG; close LOG;
EOF EOF

View File

@ -762,3 +762,22 @@ delete from t1;
set system_versioning_alter_history= keep; set system_versioning_alter_history= keep;
alter ignore table t1 drop pk; alter ignore table t1 drop pk;
drop table t1; 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;

View File

@ -653,3 +653,25 @@ set system_versioning_alter_history= keep;
alter ignore table t1 drop pk; alter ignore table t1 drop pk;
# cleanup # cleanup
drop table t1; 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;

View File

@ -29,6 +29,10 @@
#endif #endif
#ifdef MY_CONTEXT_USE_UCONTEXT #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 :-( The makecontext() only allows to pass integers into the created context :-(
We want to pass pointers, so we do it this kinda hackish way. 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); DBUG_FREE_CODE_STATE(&c->dbug_state);
} }
#ifdef __APPLE__
#pragma GCC diagnostic pop
#endif
#endif /* MY_CONTEXT_USE_UCONTEXT */ #endif /* MY_CONTEXT_USE_UCONTEXT */

View File

@ -2394,7 +2394,7 @@ Field *Field::make_new_field(MEM_ROOT *root, TABLE *new_table,
tmp->unireg_check= Field::NONE; tmp->unireg_check= Field::NONE;
tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG | tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_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); VERS_UPDATE_UNVERSIONED_FLAG);
tmp->reset_fields(); tmp->reset_fields();
tmp->invisible= VISIBLE; tmp->invisible= VISIBLE;

View File

@ -1600,7 +1600,7 @@ public:
bool vers_sys_field() const 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 bool vers_update_unversioned() const
@ -4805,7 +4805,7 @@ public:
} }
bool vers_sys_field() const 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_bit();
void create_length_to_internal_length_newdecimal(); void create_length_to_internal_length_newdecimal();
@ -5175,6 +5175,15 @@ public:
} }
/* Used to make a clone of this object for ALTER/CREATE TABLE */ /* Used to make a clone of this object for ALTER/CREATE TABLE */
Create_field *clone(MEM_ROOT *mem_root) const; 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;
}; };

View File

@ -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 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 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) 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); period= start_end_t(default_start, default_end);
as_row= period; as_row= period;
if (vers_create_sys_field(thd, default_start, alter_info, VERS_SYS_START_FLAG) || if (vers_create_sys_field(thd, default_start, alter_info, VERS_ROW_START) ||
vers_create_sys_field(thd, default_end, alter_info, VERS_SYS_END_FLAG)) vers_create_sys_field(thd, default_end, alter_info, VERS_ROW_END))
{ {
return true; return true;
} }
@ -7662,7 +7662,7 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info,
return true; return true;
} }
my_error(ER_VERS_DUPLICATE_ROW_START_END, MYF(0), 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; return true;
} }
} }
@ -7767,13 +7767,13 @@ Vers_parse_info::fix_create_like(Alter_info &alter_info, HA_CREATE_INFO &create_
while ((f= it++)) while ((f= it++))
{ {
if (f->flags & VERS_SYS_START_FLAG) if (f->flags & VERS_ROW_START)
{ {
f_start= f; f_start= f;
if (f_end) if (f_end)
break; break;
} }
else if (f->flags & VERS_SYS_END_FLAG) else if (f->flags & VERS_ROW_END)
{ {
f_end= f; f_end= f;
if (f_start) if (f_start)
@ -7835,37 +7835,31 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name,
return false; 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 || if (type_handler() == &type_handler_timestamp2 &&
f->type_handler() == &type_handler_vers_trx_id; length == MAX_DATETIME_FULL_WIDTH)
} return false;
static bool is_versioning_bigint(const Create_field *f) my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), field_name.str, "TIMESTAMP(6)",
{
return is_some_bigint(f) && f->flags & UNSIGNED_FLAG &&
f->length == MY_INT64_NUM_DECIMAL_DIGITS - 1;
}
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)",
table_name.str); table_name.str);
return true; 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); "BIGINT(20) UNSIGNED", table_name.str);
return true; return true;
} }
bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name, bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
const Lex_table_name &db, const Lex_table_name &db,
Alter_info *alter_info, 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); List_iterator<Create_field> it(alter_info->create_list);
while (Create_field *f= it++) 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; 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; row_end= f;
} }
const bool expect_timestamp= if (!row_start || !row_end)
!can_native || !is_some_bigint(row_start) || !is_some_bigint(row_end);
if (expect_timestamp)
{ {
if (!is_versioning_timestamp(row_start)) my_error(ER_VERS_PERIOD_COLUMNS, MYF(0), as_row.start.str, as_row.end.str);
return require_timestamp(row_start, table_name); return true;
}
if (!is_versioning_timestamp(row_end)) if (!can_native ||
return require_timestamp(row_end, table_name); !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 else
{ {
if (!is_versioning_bigint(row_start)) if (row_start->vers_check_bigint(table_name) ||
return require_bigint(row_start, table_name); row_end->vers_check_bigint(table_name))
return true;
if (!is_versioning_bigint(row_end)) if (!TR_table::use_transaction_registry)
return require_bigint(row_end, table_name); {
} my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
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;
} }
return false; return false;

View File

@ -359,6 +359,8 @@ String *Item_aes_crypt::val_str(String *str2)
rkey, AES_KEY_LENGTH / 8, 0, 0)) rkey, AES_KEY_LENGTH / 8, 0, 0))
{ {
str2->length((uint) aes_length); str2->length((uint) aes_length);
DBUG_ASSERT(collation.collation == &my_charset_bin);
str2->set_charset(&my_charset_bin);
return str2; return str2;
} }
} }

View File

@ -30,7 +30,7 @@ bool Item_func_history::val_bool()
{ {
Item_field *f= static_cast<Item_field *>(args[0]); Item_field *f= static_cast<Item_field *>(args[0]);
DBUG_ASSERT(f->fixed); 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(); return !f->field->is_max();
} }

View File

@ -8832,7 +8832,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr)
if (global_system_variables.low_priority_updates) if (global_system_variables.low_priority_updates)
thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY; 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", sql_print_error("Invalid ft-boolean-syntax string: %s",
ft_boolean_syntax); ft_boolean_syntax);

View File

@ -8869,6 +8869,8 @@ fill_record(THD *thd, TABLE *table, Field **ptr, List<Item> &values,
if (!thd->is_error()) if (!thd->is_error())
{ {
thd->abort_on_warning= FALSE; thd->abort_on_warning= FALSE;
if (table->default_field && table->update_default_fields(ignore_errors))
goto err;
if (table->versioned()) if (table->versioned())
table->vers_update_fields(); table->vers_update_fields();
if (table->vfield && if (table->vfield &&

View File

@ -121,11 +121,13 @@ public:
*/ */
enum explain_connection_type connection_type; enum explain_connection_type connection_type;
protected:
/* /*
A node may have children nodes. When a node's explain structure is 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. created, children nodes may not yet have QPFs. This is why we store ids.
*/ */
Dynamic_array<int> children; Dynamic_array<int> children;
public:
void add_child(int select_no) void add_child(int select_no)
{ {
children.append(select_no); children.append(select_no);

View File

@ -1288,7 +1288,18 @@ values_loop_end:
abort: abort:
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED) if (lock_type == TL_WRITE_DELAYED)
{
end_delayed_insert(thd); 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 #endif
if (table != NULL) if (table != NULL)
table->file->ha_release_auto_increment(); table->file->ha_release_auto_increment();

View File

@ -8924,7 +8924,7 @@ bool LEX::last_field_generated_always_as_row_start()
Vers_parse_info &info= vers_get_info(); Vers_parse_info &info= vers_get_info();
Lex_ident *p= &info.as_row.start; Lex_ident *p= &info.as_row.start;
return last_field_generated_always_as_row_start_or_end(p, "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(); Vers_parse_info &info= vers_get_info();
Lex_ident *p= &info.as_row.end; Lex_ident *p= &info.as_row.end;
return last_field_generated_always_as_row_start_or_end(p, "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() void st_select_lex_unit::reset_distinct()

View File

@ -4663,7 +4663,8 @@ mysql_select(THD *thd,
bool free_join= 1; bool free_join= 1;
DBUG_ENTER("mysql_select"); 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; JOIN *join;
if (select_lex->join != 0) 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, will be re-evaluated again. It could be fixed, but, probably,
it's not worth doing now. 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 */ const longlong res= tab->select_cond->val_int();
if (tab == join_tab) if (join->thd->is_error())
DBUG_RETURN(NESTED_LOOP_ERROR);
if (!res)
{ {
found= 0; /* The condition attached to table tab is false */
if (not_exists_opt_is_applicable) if (tab == join_tab)
DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS); {
} found= 0;
else if (not_exists_opt_is_applicable)
{ DBUG_RETURN(NESTED_LOOP_NO_MORE_ROWS);
/* }
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 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);
}
} }
} }
} }

View File

@ -2302,11 +2302,11 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet,
} }
else else
{ {
if (field->flags & VERS_SYS_START_FLAG) if (field->flags & VERS_ROW_START)
{ {
packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS 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")); 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) 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); table->field[21]->store(STRING_WITH_LEN("ROW START"), cs);
buf.set(STRING_WITH_LEN("STORED GENERATED"), cs); buf.set(STRING_WITH_LEN("STORED GENERATED"), cs);

View File

@ -8280,7 +8280,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
def= new (thd->mem_root) Create_field(thd, field, field); def= new (thd->mem_root) Create_field(thd, field, field);
def->invisible= INVISIBLE_SYSTEM; def->invisible= INVISIBLE_SYSTEM;
alter_info->flags|= ALTER_CHANGE_COLUMN; 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; create_info->vers_info.as_row.start= def->field_name= Vers_parse_info::default_start;
else else
create_info->vers_info.as_row.end= def->field_name= Vers_parse_info::default_end; 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) !vers_system_invisible)
{ {
StringBuffer<NAME_LEN*3> tmp; 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()); 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()); append_drop_column(thd, &tmp, table->vers_end_field());
my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr()); my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr());
goto err; goto err;

View File

@ -7776,7 +7776,7 @@ Field *Type_handler_longlong::
const Column_definition_attributes *attr, const Column_definition_attributes *attr,
uint32 flags) const 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) return new (mem_root)
Field_vers_trx_id(rec.ptr(), (uint32) attr->length, Field_vers_trx_id(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(), rec.null_ptr(), rec.null_bit(),

View File

@ -1105,7 +1105,9 @@ static Sys_var_ulong Sys_flush_time(
static bool check_ftb_syntax(sys_var *self, THD *thd, set_var *var) static bool check_ftb_syntax(sys_var *self, THD *thd, set_var *var)
{ {
return ft_boolean_check_syntax_string((uchar*) 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) static bool query_cache_flush(sys_var *self, THD *thd, enum_var_type type)
{ {

View File

@ -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) || 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->check_constraint, 1) ||
check_vcol_forward_refs(field, field->default_value, 0)) check_vcol_forward_refs(field, field->default_value, 0))
{
*error_reported= true;
goto end; goto end;
}
} }
table->find_constraint_correlated_indexes(); table->find_constraint_correlated_indexes();
@ -2359,9 +2362,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (versioned) if (versioned)
{ {
if (i == vers.start_fieldno) if (i == vers.start_fieldno)
flags|= VERS_SYS_START_FLAG; flags|= VERS_ROW_START;
else if (i == vers.end_fieldno) else if (i == vers.end_fieldno)
flags|= VERS_SYS_END_FLAG; flags|= VERS_ROW_END;
if (flags & VERS_SYSTEM_FIELD) if (flags & VERS_SYSTEM_FIELD)
{ {

View File

@ -12,6 +12,7 @@
#include <mysql.h> #include <mysql.h>
#include <sql_error.h> #include <sql_error.h>
#include <stdio.h> #include <stdio.h>
#include <cassert>
#include "bsonudf.h" #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 // For calculated arrays, a local Value must be used
int lng = 0; int lng = 0;
short type, prec = 0; short type = 0, prec = 0;
bool b = n < Nod - 1; bool b = n < Nod - 1;
PVAL valp; PVAL valp;
PBVAL vlp, vp; PBVAL vlp, vp;
@ -690,7 +691,7 @@ PVAL BJNX::GetCalcValue(PGLOBAL g, PBVAL bap, int n)
break; break;
default: default:
break; DBUG_ASSERT(!"Implement new op type support.");
} // endswitch Op } // endswitch Op
return valp = AllocateValue(g, type, lng, prec); 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; uint n = 2;
int* x = GetIntArgPtr(g, args, n); int* x = GetIntArgPtr(g, args, n);
BJNX bnx(g, NULL, TYPE_STRING); 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); PBVAL jsp = bnx.MakeValue(args, 0, true, &top);
if (bnx.CheckPath(g, args, jsp, jvp, 2)) 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 (!bsp) {
if (!CheckMemory(g, initid, args, 1, true, true)) { if (!CheckMemory(g, initid, args, 1, true, true)) {
BJNX bnx(g); BJNX bnx(g);
PBVAL top, jarp; PBVAL top, jarp = NULL;
PBVAL jvp = bnx.MakeValue(args, 0, true, &top); PBVAL jvp = bnx.MakeValue(args, 0, true, &top);
if (jvp->Type == TYPE_JOB) { if (jvp->Type == TYPE_JOB) {

View File

@ -193,7 +193,7 @@ static void PROFILE_Save( FILE *file, PROFILESECTION *section )
secno++; secno++;
} }
for (key = section->key; key; key = key->next) for (key = section->key; key; key = key->next) {
if (key->name[0]) { if (key->name[0]) {
fprintf(file, "%s", SVP(key->name)); 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, "=%s", SVP(key->value));
fprintf(file, "\n"); fprintf(file, "\n");
} // endif key->name } // endif key->name
}
} // endfor section } // endfor section
} // end of PROFILE_Save } // end of PROFILE_Save

View File

@ -871,7 +871,7 @@ PBVAL BCUTIL::MakeBson(PGLOBAL g, PBVAL jsp, int n)
/***********************************************************************/ /***********************************************************************/
PBVAL BCUTIL::GetRowValue(PGLOBAL g, PBVAL row, int i) PBVAL BCUTIL::GetRowValue(PGLOBAL g, PBVAL row, int i)
{ {
int nod = Cp->Nod, n = nod - 1; int nod = Cp->Nod;
JNODE *nodes = Cp->Nodes; JNODE *nodes = Cp->Nodes;
PBVAL arp; PBVAL arp;
PBVAL bvp = NULL; PBVAL bvp = NULL;

View File

@ -795,13 +795,9 @@ loop:
/** Flush the recently written changes to the log file. /** Flush the recently written changes to the log file.
and invoke log_mutex_enter(). */ and invoke log_mutex_enter(). */
static static void log_write_flush_to_disk_low()
void
log_write_flush_to_disk_low()
{ {
/* FIXME: This is not holding log_sys.mutex while ut_a(log_sys.n_pending_flushes);
calling os_event_set()! */
ut_a(log_sys.n_pending_flushes == 1); /* No other threads here */
bool do_flush = srv_file_flush_method != SRV_O_DSYNC; 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); fil_flush(SRV_LOG_SPACE_FIRST_ID);
} }
log_mutex_enter(); log_mutex_enter();
if (do_flush) { if (do_flush) {
log_sys.flushed_to_disk_lsn = log_sys.current_flush_lsn; 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() */ /* 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) if (srv_file_flush_method != SRV_O_DSYNC)
fil_flush(SRV_LOG_SPACE_FIRST_ID); fil_flush(SRV_LOG_SPACE_FIRST_ID);

View File

@ -78,18 +78,25 @@ FT_WORD * ft_linearize(TREE *wtree, MEM_ROOT *mem_root)
DBUG_RETURN(wlist); 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; uint i, j;
if (cs->mbminlen != 1)
{
DBUG_ASSERT(0);
return 1;
}
if (!str || if (!str ||
(strlen((char*) str)+1 != sizeof(DEFAULT_FTB_SYNTAX)) || (length + 1 != sizeof(DEFAULT_FTB_SYNTAX)) ||
(str[0] != ' ' && str[1] != ' ')) (str[0] != ' ' && str[1] != ' '))
return 1; return 1;
for (i=0; i<sizeof(DEFAULT_FTB_SYNTAX); i++) for (i=0; i<sizeof(DEFAULT_FTB_SYNTAX); i++)
{ {
/* limiting to 7-bit ascii only */ /* 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; return 1;
for (j=0; j<i; j++) for (j=0; j<i; j++)
if (str[i] == str[j] && (i != 11 || j != 10)) if (str[i] == str[j] && (i != 11 || j != 10))