summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-09-13 12:12:05 +0400
committerAlexander Barkov <bar@mariadb.org>2017-09-13 12:12:05 +0400
commit178540b904f3eca70488a3d1a0a55f5676087c04 (patch)
treec6b011a292ea8a3510dae01aa3ea43e87cf3662f
parent3a9ee22ba924160cbc5a4dd3fd047d62f11dabd2 (diff)
parenta237a920991f417e9a4567957f4fc7aa5b538270 (diff)
downloadmariadb-git-178540b904f3eca70488a3d1a0a55f5676087c04.tar.gz
Merge remote-tracking branch 'origin/10.2' into bb-10.2-ext
-rw-r--r--extra/mariabackup/backup_mysql.cc94
-rw-r--r--extra/mariabackup/xtrabackup.cc49
-rw-r--r--extra/mariabackup/xtrabackup.h4
-rw-r--r--mysql-test/r/func_json.result30
-rw-r--r--mysql-test/r/view.result23
-rw-r--r--mysql-test/suite/innodb_gis/r/rtree.result6
-rw-r--r--mysql-test/suite/json/r/json_no_table.result3
-rw-r--r--mysql-test/suite/mariabackup/lock_ddl_per_table.result4
-rw-r--r--mysql-test/suite/mariabackup/lock_ddl_per_table.test12
-rw-r--r--mysql-test/suite/mariabackup/suite.opt2
-rw-r--r--mysql-test/t/func_json.test38
-rw-r--r--mysql-test/t/view.test21
-rw-r--r--sql/item_geofunc.h13
-rw-r--r--sql/item_jsonfunc.cc32
-rw-r--r--sql/item_jsonfunc.h1
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--storage/innobase/include/log0crypt.h9
-rw-r--r--storage/innobase/log/log0crypt.cc21
-rw-r--r--storage/innobase/log/log0log.cc10
-rw-r--r--storage/innobase/log/log0recv.cc4
-rw-r--r--storage/innobase/srv/srv0start.cc15
-rw-r--r--storage/innobase/trx/trx0trx.cc1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/include/index_merge1.inc8
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result8
-rw-r--r--strings/json_lib.c2
25 files changed, 354 insertions, 58 deletions
diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc
index edd369e6ea9..60985dbb519 100644
--- a/extra/mariabackup/backup_mysql.cc
+++ b/extra/mariabackup/backup_mysql.cc
@@ -117,6 +117,7 @@ xb_mysql_connect()
mysql_options(connection, MYSQL_PLUGIN_DIR, xb_plugin_dir);
}
mysql_options(connection, MYSQL_OPT_PROTOCOL, &opt_protocol);
+ mysql_options(connection,MYSQL_SET_CHARSET_NAME, "utf8");
msg_ts("Connecting to MySQL server host: %s, user: %s, password: %s, "
"port: %s, socket: %s\n", opt_host ? opt_host : "localhost",
@@ -1629,3 +1630,96 @@ backup_cleanup()
mysql_close(mysql_connection);
}
}
+
+
+static pthread_mutex_t mdl_lock_con_mutex;
+static MYSQL *mdl_con = NULL;
+
+void
+mdl_lock_init()
+{
+ pthread_mutex_init(&mdl_lock_con_mutex, NULL);
+ mdl_con = xb_mysql_connect();
+ if (mdl_con)
+ {
+ xb_mysql_query(mdl_con, "BEGIN", false, true);
+ }
+}
+
+#ifndef DBUF_OFF
+/* Test that table is really locked, if lock_ddl_per_table is set.
+ The test is executed in DBUG_EXECUTE_IF block inside mdl_lock_table().
+*/
+static void check_mdl_lock_works(const char *table_name)
+{
+ MYSQL *test_con= xb_mysql_connect();
+ char *query;
+ xb_a(asprintf(&query,
+ "SET STATEMENT max_statement_time=1 FOR ALTER TABLE %s"
+ " ADD COLUMN mdl_lock_column int", table_name));
+ int err = mysql_query(test_con, query);
+ DBUG_ASSERT(err);
+ int err_no = mysql_errno(test_con);
+ DBUG_ASSERT(err_no == ER_STATEMENT_TIMEOUT);
+ mysql_close(test_con);
+}
+#endif
+
+extern void
+dict_fs2utf8(const char*, char*, size_t, char*, size_t);
+
+void
+mdl_lock_table(ulint space_id)
+{
+ char *query;
+
+ pthread_mutex_lock(&mdl_lock_con_mutex);
+
+ xb_a(asprintf(&query,
+ "SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES "
+ "WHERE SPACE = %llu AND NAME LIKE '%%/%%'", (ulonglong)space_id));
+
+ xb_mysql_query(mdl_con, query, true, true);
+
+ MYSQL_RES *mysql_result = xb_mysql_query(mdl_con, query, true);
+
+ MYSQL_ROW row;
+ while ((row = mysql_fetch_row(mysql_result))) {
+ char full_table_name[2*FN_REFLEN +2];
+ char db_utf8[FN_REFLEN];
+ char table_utf8[FN_REFLEN];
+
+ dict_fs2utf8(row[0], db_utf8, sizeof(db_utf8),table_utf8,sizeof(table_utf8));
+ snprintf(full_table_name,sizeof(full_table_name),"`%s`.`%s`",db_utf8,table_utf8);
+
+ char *lock_query;
+
+ msg_ts("Locking MDL for %s\n", full_table_name);
+
+ xb_a(asprintf(&lock_query,
+ "SELECT * FROM %s LIMIT 0",
+ full_table_name));
+
+ xb_mysql_query(mdl_con, lock_query, false, false);
+
+ free(lock_query);
+
+ DBUG_EXECUTE_IF("check_mdl_lock_works",
+ check_mdl_lock_works(full_table_name););
+ }
+
+ mysql_free_result(mysql_result);
+ free(query);
+ pthread_mutex_unlock(&mdl_lock_con_mutex);
+}
+
+
+void
+mdl_unlock_all()
+{
+ msg_ts("Unlocking MDL for all tables");
+ xb_mysql_query(mdl_con, "COMMIT", false, true);
+ mysql_close(mdl_con);
+ pthread_mutex_destroy(&mdl_lock_con_mutex);
+}
+
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 65aa913cc29..0027de960c1 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -296,6 +296,8 @@ my_bool opt_noversioncheck = FALSE;
my_bool opt_no_backup_locks = FALSE;
my_bool opt_decompress = FALSE;
+my_bool opt_lock_ddl_per_table = FALSE;
+
static const char *binlog_info_values[] = {"off", "lockless", "on", "auto",
NullS};
static TYPELIB binlog_info_typelib = {array_elements(binlog_info_values)-1, "",
@@ -537,7 +539,8 @@ enum options_xtrabackup
OPT_XTRA_TABLES_EXCLUDE,
OPT_XTRA_DATABASES_EXCLUDE,
- OPT_PROTOCOL
+ OPT_PROTOCOL,
+ OPT_LOCK_DDL_PER_TABLE
};
struct my_option xb_client_options[] =
@@ -1072,6 +1075,11 @@ struct my_option xb_server_options[] =
(G_PTR*) &xb_open_files_limit, (G_PTR*) &xb_open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0},
+ {"lock-ddl-per-table", OPT_LOCK_DDL_PER_TABLE, "Lock DDL for each table "
+ "before xtrabackup starts to copy it and until the backup is completed.",
+ (uchar*) &opt_lock_ddl_per_table, (uchar*) &opt_lock_ddl_per_table, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -2205,6 +2213,10 @@ xtrabackup_copy_datafile(fil_node_t* node, uint thread_n)
return(FALSE);
}
+ if (opt_lock_ddl_per_table) {
+ mdl_lock_table(node->space->id);
+ }
+
if (!changed_page_bitmap) {
read_filter = &rf_pass_through;
}
@@ -2347,10 +2359,18 @@ xtrabackup_copy_log(copy_logfile copy, lsn_t start_lsn, lsn_t end_lsn)
scanned_checkpoint = checkpoint;
ulint data_len = log_block_get_data_len(log_block);
- scanned_lsn += data_len;
- if (data_len != OS_FILE_LOG_BLOCK_SIZE) {
- /* The current end of the log was reached. */
+ if (data_len == OS_FILE_LOG_BLOCK_SIZE) {
+ /* We got a full log block. */
+ scanned_lsn += data_len;
+ } else if (data_len
+ >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE
+ || data_len <= LOG_BLOCK_HDR_SIZE) {
+ /* We got a garbage block (abrupt end of the log). */
+ break;
+ } else {
+ /* We got a partial block (abrupt end of the log). */
+ scanned_lsn += data_len;
break;
}
}
@@ -2363,7 +2383,7 @@ xtrabackup_copy_log(copy_logfile copy, lsn_t start_lsn, lsn_t end_lsn)
if (ulint write_size = ulint(end_lsn - start_lsn)) {
if (srv_encrypt_log) {
- log_crypt(log_sys->buf, write_size);
+ log_crypt(log_sys->buf, start_lsn, write_size);
}
if (ds_write(dst_log_file, log_sys->buf, write_size)) {
@@ -3552,6 +3572,10 @@ xtrabackup_backup_func()
"or RENAME TABLE during the backup, inconsistent backup will be "
"produced.\n");
+ if (opt_lock_ddl_per_table) {
+ mdl_lock_init();
+ }
+
/* initialize components */
if(innodb_init_param()) {
fail:
@@ -3741,10 +3765,10 @@ old_format:
const byte* buf = log_sys->checkpoint_buf;
- checkpoint_lsn_start = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
- checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
-
reread_log_header:
+ checkpoint_lsn_start = log_sys->log.lsn;
+ checkpoint_no_start = log_sys->next_checkpoint_no;
+
err = recv_find_max_checkpoint(&max_cp_field);
if (err != DB_SUCCESS) {
@@ -3758,10 +3782,9 @@ reread_log_header:
ut_ad(!((log_sys->log.format ^ LOG_HEADER_FORMAT_CURRENT)
& ~LOG_HEADER_FORMAT_ENCRYPTED));
- if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) {
+ log_group_header_read(&log_sys->log, max_cp_field);
- checkpoint_lsn_start = mach_read_from_8(buf + LOG_CHECKPOINT_LSN);
- checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
+ if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) {
goto reread_log_header;
}
@@ -3930,6 +3953,10 @@ reread_log_header:
goto fail;
}
+ if (opt_lock_ddl_per_table) {
+ mdl_unlock_all();
+ }
+
xtrabackup_destroy_datasinks();
msg("xtrabackup: Redo log (from LSN " LSN_PF " to " LSN_PF
diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h
index b226a9d1d83..a24626c48bc 100644
--- a/extra/mariabackup/xtrabackup.h
+++ b/extra/mariabackup/xtrabackup.h
@@ -193,4 +193,8 @@ xb_get_one_option(int optid,
const char*
xb_get_copy_action(const char *dflt = "Copying");
+void mdl_lock_init();
+void mdl_lock_table(ulint space_id);
+void mdl_unlock_all();
+
#endif /* XB_XTRABACKUP_H */
diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result
index 81c0e440a30..f8a4f3572d5 100644
--- a/mysql-test/r/func_json.result
+++ b/mysql-test/r/func_json.result
@@ -669,6 +669,36 @@ JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1
select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"');
JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"')
"\u00f6"
+select JSON_EXTRACT('{"foo": "bar" foobar foo invalid ', '$.foo');
+JSON_EXTRACT('{"foo": "bar" foobar foo invalid ', '$.foo')
+NULL
+Warnings:
+Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 15
+SELECT JSON_OBJECT('foo', '`');
+JSON_OBJECT('foo', '`')
+{"foo": "`"}
+SELECT JSON_OBJECT("foo", "bar`bar");
+JSON_OBJECT("foo", "bar`bar")
+{"foo": "bar`bar"}
+SELECT JSON_SET('{}', '$.age', 87);
+JSON_SET('{}', '$.age', 87)
+{"age": 87}
+SELECT JSON_MERGE('[]', '{"c":"d"}');
+JSON_MERGE('[]', '{"c":"d"}')
+[{"c": "d"}]
+SET @str = "{\"\\u00e4\\u00f6\":\"yes\"}";
+SET @path = "$.\"\\u00e4\\u00f6\"";
+select @str, @path, JSON_EXTRACT(@str, @path);
+@str @path JSON_EXTRACT(@str, @path)
+{"\u00e4\u00f6":"yes"} $."\u00e4\u00f6" "yes"
+SET @str = "{\"\\u00e4\":\"yes\"}";
+SET @path = "$.\"\\u00e4\"";
+select @str, @path, JSON_EXTRACT(@str, @path);
+@str @path JSON_EXTRACT(@str, @path)
+{"\u00e4":"yes"} $."\u00e4" "yes"
+select json_array(5,json_query('[1,2]','$'));
+json_array(5,json_query('[1,2]','$'))
+[5, [1,2]]
#
# Start of 10.3 tests
#
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 8767b737ca7..36abece7743 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -6638,6 +6638,29 @@ drop table procViewTable;
use test;
drop database bugTest;
#
+# MDEV-13436: PREPARE doesn't work as expected & throws errors but
+# MySQL is working fine
+#
+create table t1 (a int);
+insert into t1 values (1),(2);
+SET @sql_query = "
+ CREATE VIEW v1 AS
+ SELECT * FROM (
+ SELECT CASE WHEN 1 IN (SELECT a from t1 where a < 2) THEN TRUE END AS testcase
+ ) testalias
+";
+PREPARE stmt FROM @sql_query;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+show create view v1;
+View Create View character_set_client collation_connection
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `testalias`.`testcase` AS `testcase` from (select case when 1 in (select `test`.`t1`.`a` from `test`.`t1` where `test`.`t1`.`a` < 2) then 1 end AS `testcase`) `testalias` latin1 latin1_swedish_ci
+SELECT * FROM v1;
+testcase
+1
+drop view v1;
+drop table t1;
+#
# End of 10.2 tests
#
#
diff --git a/mysql-test/suite/innodb_gis/r/rtree.result b/mysql-test/suite/innodb_gis/r/rtree.result
index 285a499b16c..d6604314909 100644
--- a/mysql-test/suite/innodb_gis/r/rtree.result
+++ b/mysql-test/suite/innodb_gis/r/rtree.result
@@ -56,6 +56,7 @@ INSERT INTO t1 VALUES("left3", ST_GeomFromText('POLYGON (( -3 0, -3 2, -1 2, -1
SET @p = ST_GeomFromText('POLYGON (( 0 0, 0 2, 2 2, 2 0, 0 0))');
SELECT name, ST_AsText(square) from t1 where MBRContains(@p, square);
name ST_AsText(square)
+small POLYGON((0 0,0 1,1 1,1 0,0 0))
SELECT name, ST_AsText(square) from t1 where MBRDisjoint(@p, square);
name ST_AsText(square)
up3 POLYGON((0 3,0 5,2 5,2 3,0 3))
@@ -90,6 +91,7 @@ down2 POLYGON((0 -2,0 0,2 0,2 -2,0 -2))
left2 POLYGON((-2 0,-2 2,0 2,0 0,-2 0))
SELECT name, ST_AsText(square) from t1 where MBRWithin(@p, square);
name ST_AsText(square)
+big POLYGON((0 0,0 3,3 3,3 0,0 0))
SET @vert1 = ST_GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
SET @horiz1 = ST_GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
SET @horiz2 = ST_GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
@@ -217,7 +219,7 @@ SELECT COUNT(*)
FROM t1
WHERE ST_CONTAINS(ST_GeomFromText('POLYGON((2 2,4 2, 4 4, 2 4, 2 2))'),way);
COUNT(*)
-0
+9
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
@@ -226,7 +228,7 @@ SELECT COUNT(*)
FROM t1
WHERE ST_CONTAINS(ST_GeomFromText('POLYGON((2 2,4 2, 4 4, 2 4, 2 2))'),way);
COUNT(*)
-0
+9
DROP TABLE t1;
CREATE TABLE t1( i INT, g GEOMETRY NOT NULL, SPATIAL INDEX (g)) ENGINE=InnoDB;
INSERT INTO t1 VALUES(1, LINESTRING(POINT(1,1), POINT(4, 4)));
diff --git a/mysql-test/suite/json/r/json_no_table.result b/mysql-test/suite/json/r/json_no_table.result
index cf4cd5b8af8..034a4e6c0a6 100644
--- a/mysql-test/suite/json/r/json_no_table.result
+++ b/mysql-test/suite/json/r/json_no_table.result
@@ -2109,10 +2109,9 @@ ERROR 42000: Incorrect parameter count in the call to native function 'json_set'
error ER_INVALID_JSON_TEXT_IN_PARAM
SELECT JSON_SET('{}', '$.name', JSON_EXTRACT('', '$'));
JSON_SET('{}', '$.name', JSON_EXTRACT('', '$'))
-NULL
+{"name": null}
Warnings:
Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract'
-Warning 4038 Syntax error in JSON text in argument 1 to function 'json_set' at position 2
select json_set('[1,2,3]', '$[2]', 4);
json_set('[1,2,3]', '$[2]', 4)
[1, 2, 4]
diff --git a/mysql-test/suite/mariabackup/lock_ddl_per_table.result b/mysql-test/suite/mariabackup/lock_ddl_per_table.result
new file mode 100644
index 00000000000..d0137a1e072
--- /dev/null
+++ b/mysql-test/suite/mariabackup/lock_ddl_per_table.result
@@ -0,0 +1,4 @@
+CREATE TABLE t(i INT) ENGINE INNODB;
+INSERT INTO t VALUES(1);
+# xtrabackup backup
+DROP TABLE t;
diff --git a/mysql-test/suite/mariabackup/lock_ddl_per_table.test b/mysql-test/suite/mariabackup/lock_ddl_per_table.test
new file mode 100644
index 00000000000..5b45aa7c61b
--- /dev/null
+++ b/mysql-test/suite/mariabackup/lock_ddl_per_table.test
@@ -0,0 +1,12 @@
+--source include/have_debug.inc
+
+CREATE TABLE t(i INT) ENGINE INNODB;
+INSERT INTO t VALUES(1);
+echo # xtrabackup backup;
+let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
+
+--disable_result_log
+exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir --lock-ddl-per-table=1 --dbug=+d,check_mdl_lock_works;
+--enable_result_log
+DROP TABLE t;
+rmdir $targetdir; \ No newline at end of file
diff --git a/mysql-test/suite/mariabackup/suite.opt b/mysql-test/suite/mariabackup/suite.opt
index ba78b2d8957..defba074293 100644
--- a/mysql-test/suite/mariabackup/suite.opt
+++ b/mysql-test/suite/mariabackup/suite.opt
@@ -1 +1 @@
---innodb --loose-changed_page_bitmaps --innodb-file-format=Barracuda \ No newline at end of file
+--innodb --loose-changed_page_bitmaps --innodb-file-format=Barracuda --innodb-sys-tables \ No newline at end of file
diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test
index 823421520c8..14479d0df1b 100644
--- a/mysql-test/t/func_json.test
+++ b/mysql-test/t/func_json.test
@@ -317,6 +317,44 @@ select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false;
select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1;
select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"');
+#
+# MDEV-129892 JSON_EXTRACT returns data for invalid JSON
+#
+select JSON_EXTRACT('{"foo": "bar" foobar foo invalid ', '$.foo');
+
+#
+# MDEV-13138 JSON_OBJECT returns null with strings containing backticks.
+#
+SELECT JSON_OBJECT('foo', '`');
+SELECT JSON_OBJECT("foo", "bar`bar");
+
+#
+# MDEV-13324 JSON_SET returns NULL instead of object.
+#
+SELECT JSON_SET('{}', '$.age', 87);
+
+#
+# MDEV-13104 Json functions.
+#
+SELECT JSON_MERGE('[]', '{"c":"d"}');
+
+#
+# MDEV-12774 JSON_EXTRACT fails with some escaped unicode as key.
+#
+
+SET @str = "{\"\\u00e4\\u00f6\":\"yes\"}";
+SET @path = "$.\"\\u00e4\\u00f6\"";
+select @str, @path, JSON_EXTRACT(@str, @path);
+SET @str = "{\"\\u00e4\":\"yes\"}";
+SET @path = "$.\"\\u00e4\"";
+select @str, @path, JSON_EXTRACT(@str, @path);
+
+#
+# MDEV-12877 Wrong result from JSON native function.
+#
+select json_array(5,json_query('[1,2]','$'));
+
+
--echo #
--echo # Start of 10.3 tests
--echo #
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index fc6ee46c1ac..00be48c172c 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -6351,6 +6351,27 @@ use test;
drop database bugTest;
--echo #
+--echo # MDEV-13436: PREPARE doesn't work as expected & throws errors but
+--echo # MySQL is working fine
+--echo #
+
+create table t1 (a int);
+insert into t1 values (1),(2);
+SET @sql_query = "
+ CREATE VIEW v1 AS
+ SELECT * FROM (
+ SELECT CASE WHEN 1 IN (SELECT a from t1 where a < 2) THEN TRUE END AS testcase
+ ) testalias
+";
+PREPARE stmt FROM @sql_query;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+show create view v1;
+SELECT * FROM v1;
+drop view v1;
+drop table t1;
+
+--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index db720da18fd..d332d067c37 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -550,7 +550,18 @@ public:
maybe_null= true;
}
enum Functype functype() const { return spatial_rel; }
- enum Functype rev_functype() const { return spatial_rel; }
+ enum Functype rev_functype() const
+ {
+ switch (spatial_rel)
+ {
+ case SP_CONTAINS_FUNC:
+ return SP_WITHIN_FUNC;
+ case SP_WITHIN_FUNC:
+ return SP_CONTAINS_FUNC;
+ default:
+ return spatial_rel;
+ }
+ }
bool is_null() { (void) val_int(); return null_value; }
void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
uint *and_level, table_map usable_tables,
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index dbaf2c6f6a3..4585427b442 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -650,6 +650,7 @@ static int alloc_tmp_paths(THD *thd, uint n_paths,
if (*tmp_paths == 0)
{
MEM_ROOT *root= thd->stmt_arena->mem_root;
+
*paths= (json_path_with_flags *) alloc_root(root,
sizeof(json_path_with_flags) * n_paths);
*tmp_paths= (String *) alloc_root(root, sizeof(String) * n_paths);
@@ -657,6 +658,8 @@ static int alloc_tmp_paths(THD *thd, uint n_paths,
return 1;
bzero(*tmp_paths, sizeof(String) * n_paths);
+ for (uint c_path=0; c_path < n_paths; c_path++)
+ (*tmp_paths)[c_path].set_charset(&my_charset_utf8_general_ci);
}
return 0;
@@ -821,7 +824,11 @@ String *Item_func_json_extract::read_json(String *str,
not_first_value= 1;
if (!possible_multiple_values)
+ {
+ /* Loop to the end of the JSON just to make sure it's valid. */
+ while (json_get_path_next(&je, &p) == 0) {}
break;
+ }
}
if (je.s.error)
@@ -869,7 +876,7 @@ longlong Item_func_json_extract::val_int()
json_value_types type;
char *value;
int value_len;
- longlong i;
+ longlong i= 0;
if (read_json(NULL, &type, &value, &value_len) != NULL)
{
@@ -1968,14 +1975,25 @@ continue_j2:
else
{
const uchar *end1, *beg1, *end2, *beg2;
+ int empty_array= 0;
beg1= je1->value_begin;
/* Merge as a single array. */
if (je1->value_type == JSON_VALUE_ARRAY)
{
- if (json_skip_level(je1))
+ int cur_level= je1->stack_p;
+ empty_array= 1;
+ while (json_scan_next(je1) == 0)
+ {
+ if (je1->stack_p < cur_level)
+ break;
+ empty_array= 0;
+ }
+
+ if (je1->s.error)
return 1;
+
end1= je1->s.c_str - je1->sav_c_len;
}
else
@@ -1992,8 +2010,8 @@ continue_j2:
end1= je1->value_end;
}
- if (str->append((const char*) beg1, end1 - beg1),
- str->append(", ", 2))
+ if (str->append((const char*) beg1, end1 - beg1) ||
+ (!empty_array && str->append(", ", 2)))
return 3;
if (json_value_scalar(je2))
@@ -2449,6 +2467,8 @@ String *Item_func_json_insert::val_str(String *str)
}
else /*JSON_PATH_KEY*/
{
+ uint n_key= 0;
+
if (je.value_type != JSON_VALUE_OBJECT)
continue;
@@ -2460,6 +2480,7 @@ String *Item_func_json_insert::val_str(String *str)
json_string_set_str(&key_name, lp->key, lp->key_end);
if (json_key_matches(&je, &key_name))
goto v_found;
+ n_key++;
if (json_skip_key(&je))
goto js_error;
break;
@@ -2477,7 +2498,8 @@ String *Item_func_json_insert::val_str(String *str)
v_to= (const char *) (je.s.c_str - je.sav_c_len);
str->length(0);
if (append_simple(str, js->ptr(), v_to - js->ptr()) ||
- str->append(", \"", 3) ||
+ (n_key > 0 && str->append(", ", 2)) ||
+ str->append("\"", 1) ||
append_simple(str, lp->key, lp->key_end - lp->key) ||
str->append("\":", 2) ||
append_json_value(str, args[n_arg+1], &tmp_val) ||
diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h
index 97f144c0fd3..7da72dc7f89 100644
--- a/sql/item_jsonfunc.h
+++ b/sql/item_jsonfunc.h
@@ -99,6 +99,7 @@ class Item_func_json_query: public Item_func_json_value
public:
Item_func_json_query(THD *thd, Item *js, Item *i_path):
Item_func_json_value(thd, js, i_path) {}
+ bool is_json_type() { return true; }
const char *func_name() const { return "json_query"; }
bool check_and_get_value(json_engine_t *je, String *res, int *error);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 997ff2aeb38..f83df07a80f 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2085,11 +2085,11 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
if (thd->open_temporary_tables(tables))
goto err;
+ lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL,
DT_PREPARE))
goto err;
- lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
res= select_like_stmt_test(stmt, 0, 0);
err:
diff --git a/storage/innobase/include/log0crypt.h b/storage/innobase/include/log0crypt.h
index d1282043665..a5f7c56cc3f 100644
--- a/storage/innobase/include/log0crypt.h
+++ b/storage/innobase/include/log0crypt.h
@@ -32,7 +32,11 @@ MDEV-11782: Rewritten for MariaDB 10.2 by Marko Mäkelä, MariaDB Corporation.
/** innodb_encrypt_log: whether to encrypt the redo log */
extern my_bool srv_encrypt_log;
-/** Initialize the redo log encryption key.
+/** Initialize the redo log encryption key and random parameters
+when creating a new redo log.
+The random parameters will be persisted in the log checkpoint pages.
+@see log_crypt_write_checkpoint_buf()
+@see log_crypt_read_checkpoint_buf()
@return whether the operation succeeded */
UNIV_INTERN
bool
@@ -71,10 +75,11 @@ log_crypt_read_checkpoint_buf(const byte* buf);
/** Encrypt or decrypt log blocks.
@param[in,out] buf log blocks to encrypt or decrypt
+@param[in] lsn log sequence number of the start of the buffer
@param[in] size size of the buffer, in bytes
@param[in] decrypt whether to decrypt instead of encrypting */
UNIV_INTERN
void
-log_crypt(byte* buf, ulint size, bool decrypt = false);
+log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt = false);
#endif // log0crypt.h
diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc
index 69cfec10fed..c0a10c74073 100644
--- a/storage/innobase/log/log0crypt.cc
+++ b/storage/innobase/log/log0crypt.cc
@@ -103,11 +103,12 @@ get_crypt_info(ulint checkpoint_no)
/** Encrypt or decrypt log blocks.
@param[in,out] buf log blocks to encrypt or decrypt
+@param[in] lsn log sequence number of the start of the buffer
@param[in] size size of the buffer, in bytes
@param[in] decrypt whether to decrypt instead of encrypting */
UNIV_INTERN
void
-log_crypt(byte* buf, ulint size, bool decrypt)
+log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt)
{
ut_ad(size % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a(info.key_version);
@@ -117,12 +118,12 @@ log_crypt(byte* buf, ulint size, bool decrypt)
compile_time_assert(sizeof(uint32_t) == 4);
#define LOG_CRYPT_HDR_SIZE 4
+ lsn &= ~lsn_t(OS_FILE_LOG_BLOCK_SIZE - 1);
for (const byte* const end = buf + size; buf != end;
- buf += OS_FILE_LOG_BLOCK_SIZE) {
+ buf += OS_FILE_LOG_BLOCK_SIZE, lsn += OS_FILE_LOG_BLOCK_SIZE) {
uint32_t dst[(OS_FILE_LOG_BLOCK_SIZE - LOG_CRYPT_HDR_SIZE)
/ sizeof(uint32_t)];
- const ulint log_block_no = log_block_get_hdr_no(buf);
/* The log block number is not encrypted. */
*aes_ctr_iv =
@@ -137,10 +138,10 @@ log_crypt(byte* buf, ulint size, bool decrypt)
# error "LOG_BLOCK_HDR_NO has been moved; redo log format affected!"
#endif
aes_ctr_iv[1] = info.crypt_nonce.word;
- mach_write_to_8(reinterpret_cast<byte*>(aes_ctr_iv + 2),
- log_block_get_start_lsn(
- decrypt ? srv_start_lsn : log_sys->lsn,
- log_block_no));
+ mach_write_to_8(reinterpret_cast<byte*>(aes_ctr_iv + 2), lsn);
+ ut_ad(log_block_get_start_lsn(lsn,
+ log_block_get_hdr_no(buf))
+ == lsn);
int rc = encryption_crypt(
buf + LOG_CRYPT_HDR_SIZE, sizeof dst,
@@ -206,7 +207,11 @@ init_crypt_key(crypt_info_t* info, bool upgrade = false)
return true;
}
-/** Initialize the redo log encryption key.
+/** Initialize the redo log encryption key and random parameters
+when creating a new redo log.
+The random parameters will be persisted in the log checkpoint pages.
+@see log_crypt_write_checkpoint_buf()
+@see log_crypt_read_checkpoint_buf()
@return whether the operation succeeded */
UNIV_INTERN
bool
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 463914982cf..f7974d243d8 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -997,10 +997,6 @@ loop:
|| log_block_get_hdr_no(buf)
== log_block_convert_lsn_to_no(start_lsn));
- if (log_sys->is_encrypted()) {
- log_crypt(buf, write_len);
- }
-
/* Calculate the checksums for each log block and write them to
the trailer fields of the log blocks */
@@ -1264,6 +1260,12 @@ loop:
::memset(write_buf + area_end, 0, pad_size);
}
}
+
+ if (log_sys->is_encrypted()) {
+ log_crypt(write_buf + area_start, log_sys->write_lsn,
+ area_end - area_start);
+ }
+
/* Do the write to the log files */
log_group_write_buf(
&log_sys->log, write_buf + area_start,
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 8bc8df750e4..fd0940b08df 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -715,7 +715,8 @@ loop:
}
if (group->is_encrypted()) {
- log_crypt(buf, OS_FILE_LOG_BLOCK_SIZE, true);
+ log_crypt(buf, start_lsn,
+ OS_FILE_LOG_BLOCK_SIZE, true);
}
}
}
@@ -1016,6 +1017,7 @@ recv_find_max_checkpoint(ulint* max_field)
buf + LOG_CHECKPOINT_LSN);
group->lsn_offset = mach_read_from_8(
buf + LOG_CHECKPOINT_OFFSET);
+ log_sys->next_checkpoint_no = checkpoint_no;
}
}
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 21c1343f5b3..66866c98e62 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -2223,14 +2223,6 @@ files_checked:
recv_sys->dblwr.pages.clear();
- if (err == DB_SUCCESS && !srv_read_only_mode) {
- log_mutex_enter();
- if (log_sys->is_encrypted() && !log_crypt_init()) {
- err = DB_ERROR;
- }
- log_mutex_exit();
- }
-
if (err == DB_SUCCESS) {
/* Initialize the change buffer. */
err = dict_boot();
@@ -2733,13 +2725,6 @@ files_checked:
fil_crypt_threads_init();
fil_system_exit();
- /*
- Create a checkpoint before logging anything new, so that
- the current encryption key in use is definitely logged
- before any log blocks encrypted with that key.
- */
- log_make_checkpoint_at(LSN_MAX, TRUE);
-
/* Initialize online defragmentation. */
btr_defragment_init();
btr_defragment_thread_active = true;
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index ac23234179c..2408e4bdaf4 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -619,6 +619,7 @@ trx_free_prepared(
|| (trx_state_eq(trx, TRX_STATE_ACTIVE)
&& trx->is_recovered
&& (!srv_was_started
+ || srv_operation == SRV_OPERATION_RESTORE
|| srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO)));
ut_a(trx->magic_n == TRX_MAGIC_N);
diff --git a/storage/rocksdb/mysql-test/rocksdb/include/index_merge1.inc b/storage/rocksdb/mysql-test/rocksdb/include/index_merge1.inc
index d18faea61a8..91bcc68adb4 100644
--- a/storage/rocksdb/mysql-test/rocksdb/include/index_merge1.inc
+++ b/storage/rocksdb/mysql-test/rocksdb/include/index_merge1.inc
@@ -402,12 +402,20 @@ analyze table t1;
-- enable_query_log
# index_merge on first table in join
+if ($index_merge_random_rows_in_EXPLAIN)
+{
+ --replace_column 9 #
+}
explain select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4;
select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4;
+if ($index_merge_random_rows_in_EXPLAIN)
+{
+ --replace_column 9 #
+}
explain
select * from t0,t1 where (t0.key1=t1.key1) and ( t0.key1=3 or t0.key2=4);
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result
index bd9983d68a4..ff33e6061b3 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result
@@ -250,8 +250,8 @@ insert into t1 select * from t0;
explain select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
-1 SIMPLE t1 ref i1 i1 4 test.t0.key1 2
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL # Using union(i1,i2); Using where
+1 SIMPLE t1 ref i1 i1 4 test.t0.key1 #
select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4;
key1 key2 key3 key4 key5 key6 key7 key8 key1 key2 key3 key4 key5 key6 key7 key8
@@ -260,8 +260,8 @@ key1 key2 key3 key4 key5 key6 key7 key8 key1 key2 key3 key4 key5 key6 key7 key8
explain
select * from t0,t1 where (t0.key1=t1.key1) and ( t0.key1=3 or t0.key2=4);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
-1 SIMPLE t1 ref i1 i1 4 test.t0.key1 2
+1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL # Using union(i1,i2); Using where
+1 SIMPLE t1 ref i1 i1 4 test.t0.key1 #
explain
select * from t0,t1 where (t0.key1=t1.key1) and
(t0.key1=3 or t0.key2<4) and t1.key1=2;
diff --git a/strings/json_lib.c b/strings/json_lib.c
index b0c843caec1..25e5e81e6f9 100644
--- a/strings/json_lib.c
+++ b/strings/json_lib.c
@@ -1586,7 +1586,7 @@ int json_escape(CHARSET_INFO *str_cs,
enum json_esc_char_classes c_class;
str+= c_len;
- if (c_chr > 0x60 || (c_class= json_escape_chr_map[c_chr]) == ESC_)
+ if (c_chr >= 0x60 || (c_class= json_escape_chr_map[c_chr]) == ESC_)
{
if ((c_len= json_cs->cset->wc_mb(json_cs, c_chr, json, json_end)) > 0)
{