Commit 178540b9 authored by Alexander Barkov's avatar Alexander Barkov

Merge remote-tracking branch 'origin/10.2' into bb-10.2-ext

parents 3a9ee22b a237a920
...@@ -117,6 +117,7 @@ xb_mysql_connect() ...@@ -117,6 +117,7 @@ xb_mysql_connect()
mysql_options(connection, MYSQL_PLUGIN_DIR, xb_plugin_dir); mysql_options(connection, MYSQL_PLUGIN_DIR, xb_plugin_dir);
} }
mysql_options(connection, MYSQL_OPT_PROTOCOL, &opt_protocol); 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, " msg_ts("Connecting to MySQL server host: %s, user: %s, password: %s, "
"port: %s, socket: %s\n", opt_host ? opt_host : "localhost", "port: %s, socket: %s\n", opt_host ? opt_host : "localhost",
...@@ -1629,3 +1630,96 @@ backup_cleanup() ...@@ -1629,3 +1630,96 @@ backup_cleanup()
mysql_close(mysql_connection); 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);
}
...@@ -296,6 +296,8 @@ my_bool opt_noversioncheck = FALSE; ...@@ -296,6 +296,8 @@ my_bool opt_noversioncheck = FALSE;
my_bool opt_no_backup_locks = FALSE; my_bool opt_no_backup_locks = FALSE;
my_bool opt_decompress = FALSE; my_bool opt_decompress = FALSE;
my_bool opt_lock_ddl_per_table = FALSE;
static const char *binlog_info_values[] = {"off", "lockless", "on", "auto", static const char *binlog_info_values[] = {"off", "lockless", "on", "auto",
NullS}; NullS};
static TYPELIB binlog_info_typelib = {array_elements(binlog_info_values)-1, "", static TYPELIB binlog_info_typelib = {array_elements(binlog_info_values)-1, "",
...@@ -537,7 +539,8 @@ enum options_xtrabackup ...@@ -537,7 +539,8 @@ enum options_xtrabackup
OPT_XTRA_TABLES_EXCLUDE, OPT_XTRA_TABLES_EXCLUDE,
OPT_XTRA_DATABASES_EXCLUDE, OPT_XTRA_DATABASES_EXCLUDE,
OPT_PROTOCOL OPT_PROTOCOL,
OPT_LOCK_DDL_PER_TABLE
}; };
struct my_option xb_client_options[] = struct my_option xb_client_options[] =
...@@ -1072,6 +1075,11 @@ struct my_option xb_server_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, (G_PTR*) &xb_open_files_limit, (G_PTR*) &xb_open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0}, 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} { 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) ...@@ -2205,6 +2213,10 @@ xtrabackup_copy_datafile(fil_node_t* node, uint thread_n)
return(FALSE); return(FALSE);
} }
if (opt_lock_ddl_per_table) {
mdl_lock_table(node->space->id);
}
if (!changed_page_bitmap) { if (!changed_page_bitmap) {
read_filter = &rf_pass_through; read_filter = &rf_pass_through;
} }
...@@ -2347,10 +2359,18 @@ xtrabackup_copy_log(copy_logfile copy, lsn_t start_lsn, lsn_t end_lsn) ...@@ -2347,10 +2359,18 @@ xtrabackup_copy_log(copy_logfile copy, lsn_t start_lsn, lsn_t end_lsn)
scanned_checkpoint = checkpoint; scanned_checkpoint = checkpoint;
ulint data_len = log_block_get_data_len(log_block); ulint data_len = log_block_get_data_len(log_block);
scanned_lsn += data_len;
if (data_len != OS_FILE_LOG_BLOCK_SIZE) { if (data_len == OS_FILE_LOG_BLOCK_SIZE) {
/* The current end of the log was reached. */ /* 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; break;
} }
} }
...@@ -2363,7 +2383,7 @@ xtrabackup_copy_log(copy_logfile copy, lsn_t start_lsn, lsn_t end_lsn) ...@@ -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 (ulint write_size = ulint(end_lsn - start_lsn)) {
if (srv_encrypt_log) { 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)) { if (ds_write(dst_log_file, log_sys->buf, write_size)) {
...@@ -3552,6 +3572,10 @@ xtrabackup_backup_func() ...@@ -3552,6 +3572,10 @@ xtrabackup_backup_func()
"or RENAME TABLE during the backup, inconsistent backup will be " "or RENAME TABLE during the backup, inconsistent backup will be "
"produced.\n"); "produced.\n");
if (opt_lock_ddl_per_table) {
mdl_lock_init();
}
/* initialize components */ /* initialize components */
if(innodb_init_param()) { if(innodb_init_param()) {
fail: fail:
...@@ -3741,10 +3765,10 @@ xtrabackup_backup_func() ...@@ -3741,10 +3765,10 @@ xtrabackup_backup_func()
const byte* buf = log_sys->checkpoint_buf; 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: 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); err = recv_find_max_checkpoint(&max_cp_field);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
...@@ -3758,10 +3782,9 @@ xtrabackup_backup_func() ...@@ -3758,10 +3782,9 @@ xtrabackup_backup_func()
ut_ad(!((log_sys->log.format ^ LOG_HEADER_FORMAT_CURRENT) ut_ad(!((log_sys->log.format ^ LOG_HEADER_FORMAT_CURRENT)
& ~LOG_HEADER_FORMAT_ENCRYPTED)); & ~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); if (checkpoint_no_start != mach_read_from_8(buf + LOG_CHECKPOINT_NO)) {
checkpoint_no_start = mach_read_from_8(buf + LOG_CHECKPOINT_NO);
goto reread_log_header; goto reread_log_header;
} }
...@@ -3930,6 +3953,10 @@ xtrabackup_backup_func() ...@@ -3930,6 +3953,10 @@ xtrabackup_backup_func()
goto fail; goto fail;
} }
if (opt_lock_ddl_per_table) {
mdl_unlock_all();
}
xtrabackup_destroy_datasinks(); xtrabackup_destroy_datasinks();
msg("xtrabackup: Redo log (from LSN " LSN_PF " to " LSN_PF msg("xtrabackup: Redo log (from LSN " LSN_PF " to " LSN_PF
......
...@@ -193,4 +193,8 @@ xb_get_one_option(int optid, ...@@ -193,4 +193,8 @@ xb_get_one_option(int optid,
const char* const char*
xb_get_copy_action(const char *dflt = "Copying"); 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 */ #endif /* XB_XTRABACKUP_H */
...@@ -669,6 +669,36 @@ JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1 ...@@ -669,6 +669,36 @@ JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1
select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"'); select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"');
JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"') JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"')
"\u00f6" "\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 # Start of 10.3 tests
# #
......
...@@ -6638,6 +6638,29 @@ drop table procViewTable; ...@@ -6638,6 +6638,29 @@ drop table procViewTable;
use test; use test;
drop database bugTest; 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 # End of 10.2 tests
# #
# #
......
...@@ -56,6 +56,7 @@ INSERT INTO t1 VALUES("left3", ST_GeomFromText('POLYGON (( -3 0, -3 2, -1 2, -1 ...@@ -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))'); 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); SELECT name, ST_AsText(square) from t1 where MBRContains(@p, square);
name ST_AsText(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); SELECT name, ST_AsText(square) from t1 where MBRDisjoint(@p, square);
name ST_AsText(square) name ST_AsText(square)
up3 POLYGON((0 3,0 5,2 5,2 3,0 3)) 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)) ...@@ -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)) left2 POLYGON((-2 0,-2 2,0 2,0 0,-2 0))
SELECT name, ST_AsText(square) from t1 where MBRWithin(@p, square); SELECT name, ST_AsText(square) from t1 where MBRWithin(@p, square);
name ST_AsText(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 @vert1 = ST_GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))');
SET @horiz1 = ST_GeomFromText('POLYGON ((-2 0, 2 0, -2 0))'); SET @horiz1 = ST_GeomFromText('POLYGON ((-2 0, 2 0, -2 0))');
SET @horiz2 = ST_GeomFromText('POLYGON ((-1 0, 3 0, -1 0))'); SET @horiz2 = ST_GeomFromText('POLYGON ((-1 0, 3 0, -1 0))');
...@@ -217,7 +219,7 @@ SELECT COUNT(*) ...@@ -217,7 +219,7 @@ SELECT COUNT(*)
FROM t1 FROM t1
WHERE ST_CONTAINS(ST_GeomFromText('POLYGON((2 2,4 2, 4 4, 2 4, 2 2))'),way); WHERE ST_CONTAINS(ST_GeomFromText('POLYGON((2 2,4 2, 4 4, 2 4, 2 2))'),way);
COUNT(*) COUNT(*)
0 9
OPTIMIZE TABLE t1; OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
...@@ -226,7 +228,7 @@ SELECT COUNT(*) ...@@ -226,7 +228,7 @@ SELECT COUNT(*)
FROM t1 FROM t1
WHERE ST_CONTAINS(ST_GeomFromText('POLYGON((2 2,4 2, 4 4, 2 4, 2 2))'),way); WHERE ST_CONTAINS(ST_GeomFromText('POLYGON((2 2,4 2, 4 4, 2 4, 2 2))'),way);
COUNT(*) COUNT(*)
0 9
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1( i INT, g GEOMETRY NOT NULL, SPATIAL INDEX (g)) ENGINE=InnoDB; 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))); INSERT INTO t1 VALUES(1, LINESTRING(POINT(1,1), POINT(4, 4)));
......
CREATE TABLE t(i INT) ENGINE INNODB;
INSERT INTO t VALUES(1);
# xtrabackup backup
DROP TABLE t;
--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
--innodb --loose-changed_page_bitmaps --innodb-file-format=Barracuda --innodb --loose-changed_page_bitmaps --innodb-file-format=Barracuda --innodb-sys-tables
\ No newline at end of file \ No newline at end of file
...@@ -317,6 +317,44 @@ select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false; ...@@ -317,6 +317,44 @@ select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = false;
select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1; select JSON_EXTRACT('{\"asdf\":true}', "$.\"asdf\"") = 1;
select JSON_EXTRACT('{\"input1\":\"\\u00f6\"}', '$.\"input1\"'); 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 #
--echo # Start of 10.3 tests --echo # Start of 10.3 tests
--echo # --echo #
......
...@@ -6350,6 +6350,27 @@ drop table procViewTable; ...@@ -6350,6 +6350,27 @@ drop table procViewTable;
use test; use test;
drop database bugTest; 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 #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #
......
...@@ -550,7 +550,18 @@ class Item_func_spatial_rel: public Item_bool_func2_with_rev ...@@ -550,7 +550,18 @@ class Item_func_spatial_rel: public Item_bool_func2_with_rev
maybe_null= true; maybe_null= true;
} }
enum Functype functype() const { return spatial_rel; } 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; } bool is_null() { (void) val_int(); return null_value; }
void add_key_fields(JOIN *join, KEY_FIELD **key_fields, void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
uint *and_level, table_map usable_tables, uint *and_level, table_map usable_tables,
......
...@@ -650,6 +650,7 @@ static int alloc_tmp_paths(THD *thd, uint n_paths, ...@@ -650,6 +650,7 @@ static int alloc_tmp_paths(THD *thd, uint n_paths,
if (*tmp_paths == 0) if (*tmp_paths == 0)
{ {
MEM_ROOT *root= thd->stmt_arena->mem_root; MEM_ROOT *root= thd->stmt_arena->mem_root;
*paths= (json_path_with_flags *) alloc_root(root, *paths= (json_path_with_flags *) alloc_root(root,
sizeof(json_path_with_flags) * n_paths); sizeof(json_path_with_flags) * n_paths);
*tmp_paths= (String *) alloc_root(root, sizeof(String) * 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, ...@@ -657,6 +658,8 @@ static int alloc_tmp_paths(THD *thd, uint n_paths,
return 1; return 1;
bzero(*tmp_paths, sizeof(String) * n_paths); 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; return 0;
...@@ -821,7 +824,11 @@ String *Item_func_json_extract::read_json(String *str, ...@@ -821,7 +824,11 @@ String *Item_func_json_extract::read_json(String *str,
not_first_value= 1; not_first_value= 1;
if (!possible_multiple_values) 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; break;
}
} }
if (je.s.error) if (je.s.error)
...@@ -869,7 +876,7 @@ longlong Item_func_json_extract::val_int() ...@@ -869,7 +876,7 @@ longlong Item_func_json_extract::val_int()
json_value_types type; json_value_types type;
char *value; char *value;
int value_len; int value_len;
longlong i; longlong i= 0;
if (read_json(NULL, &type, &value, &value_len) != NULL) if (read_json(NULL, &type, &value, &value_len) != NULL)
{ {
...@@ -1968,14 +1975,25 @@ static int do_merge(String *str, json_engine_t *je1, json_engine_t *je2) ...@@ -1968,14 +1975,25 @@ static int do_merge(String *str, json_engine_t *je1, json_engine_t *je2)
else else
{ {
const uchar *end1, *beg1, *end2, *beg2; const uchar *end1, *beg1, *end2, *beg2;
int empty_array= 0;
beg1= je1->value_begin; beg1= je1->value_begin;
/* Merge as a single array. */ /* Merge as a single array. */
if (je1->value_type == JSON_VALUE_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; return 1;
end1= je1->s.c_str - je1->sav_c_len; end1= je1->s.c_str - je1->sav_c_len;
} }
else else
...@@ -1992,8 +2010,8 @@ static int do_merge(String *str, json_engine_t *je1, json_engine_t *je2) ...@@ -1992,8 +2010,8 @@ static int do_merge(String *str, json_engine_t *je1, json_engine_t *je2)
end1= je1->value_end; end1= je1->value_end;
} }
if (str->append((const char*) beg1, end1 - beg1), if (str->append((const char*) beg1, end1 - beg1) ||
str->append(", ", 2)) (!empty_array && str->append(", ", 2)))
return 3; return 3;
if (json_value_scalar(je2)) if (json_value_scalar(je2))
...@@ -2449,6 +2467,8 @@ String *Item_func_json_insert::val_str(String *str) ...@@ -2449,6 +2467,8 @@ String *Item_func_json_insert::val_str(String *str)
} }
else /*JSON_PATH_KEY*/ else /*JSON_PATH_KEY*/
{ {
uint n_key= 0;
if (je.value_type != JSON_VALUE_OBJECT) if (je.value_type != JSON_VALUE_OBJECT)
continue; continue;
...@@ -2460,6 +2480,7 @@ String *Item_func_json_insert::val_str(String *str) ...@@ -2460,6 +2480,7 @@ String *Item_func_json_insert::val_str(String *str)
json_string_set_str(&key_name, lp->key, lp->key_end); json_string_set_str(&key_name, lp->key, lp->key_end);
if (json_key_matches(&je, &key_name)) if (json_key_matches(&je, &key_name))
goto v_found; goto v_found;
n_key++;
if (json_skip_key(&je)) if (json_skip_key(&je))
goto js_error; goto js_error;
break; break;
...@@ -2477,7 +2498,8 @@ String *Item_func_json_insert::val_str(String *str) ...@@ -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); v_to= (const char *) (je.s.c_str - je.sav_c_len);
str->length(0); str->length(0);
if (append_simple(str, js->ptr(), v_to - js->ptr()) || 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) || append_simple(str, lp->key, lp->key_end - lp->key) ||
str->append("\":", 2) || str->append("\":", 2) ||
append_json_value(str, args[n_arg+1], &tmp_val) || append_json_value(str, args[n_arg+1], &tmp_val) ||
......
...@@ -99,6 +99,7 @@ class Item_func_json_query: public Item_func_json_value ...@@ -99,6 +99,7 @@ class Item_func_json_query: public Item_func_json_value
public: public:
Item_func_json_query(THD *thd, Item *js, Item *i_path): Item_func_json_query(THD *thd, Item *js, Item *i_path):
Item_func_json_value(thd, js, i_path) {} Item_func_json_value(thd, js, i_path) {}
bool is_json_type() { return true; }
const char *func_name() const { return "json_query"; } const char *func_name() const { return "json_query"; }
bool check_and_get_value(json_engine_t *je, String *res, int *error); bool check_and_get_value(json_engine_t *je, String *res, int *error);
Item *get_copy(THD *thd, MEM_ROOT *mem_root) Item *get_copy(THD *thd, MEM_ROOT *mem_root)
......
...@@ -2085,11 +2085,11 @@ static bool mysql_test_create_view(Prepared_statement *stmt) ...@@ -2085,11 +2085,11 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
if (thd->open_temporary_tables(tables)) if (thd->open_temporary_tables(tables))
goto err; goto err;
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL, if (open_normal_and_derived_tables(thd, tables, MYSQL_OPEN_FORCE_SHARED_MDL,
DT_PREPARE)) DT_PREPARE))
goto err; goto err;
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
res= select_like_stmt_test(stmt, 0, 0); res= select_like_stmt_test(stmt, 0, 0);
err: err:
......
...@@ -32,7 +32,11 @@ MDEV-11782: Rewritten for MariaDB 10.2 by Marko Mäkelä, MariaDB Corporation. ...@@ -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 */ /** innodb_encrypt_log: whether to encrypt the redo log */
extern my_bool srv_encrypt_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 */ @return whether the operation succeeded */
UNIV_INTERN UNIV_INTERN
bool bool
...@@ -71,10 +75,11 @@ log_crypt_read_checkpoint_buf(const byte* buf); ...@@ -71,10 +75,11 @@ log_crypt_read_checkpoint_buf(const byte* buf);
/** Encrypt or decrypt log blocks. /** Encrypt or decrypt log blocks.
@param[in,out] buf log blocks to encrypt or decrypt @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] size size of the buffer, in bytes
@param[in] decrypt whether to decrypt instead of encrypting */ @param[in] decrypt whether to decrypt instead of encrypting */
UNIV_INTERN UNIV_INTERN
void 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 #endif // log0crypt.h
...@@ -103,11 +103,12 @@ get_crypt_info(ulint checkpoint_no) ...@@ -103,11 +103,12 @@ get_crypt_info(ulint checkpoint_no)
/** Encrypt or decrypt log blocks. /** Encrypt or decrypt log blocks.
@param[in,out] buf log blocks to encrypt or decrypt @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] size size of the buffer, in bytes
@param[in] decrypt whether to decrypt instead of encrypting */ @param[in] decrypt whether to decrypt instead of encrypting */
UNIV_INTERN UNIV_INTERN
void 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_ad(size % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a(info.key_version); ut_a(info.key_version);
...@@ -117,12 +118,12 @@ log_crypt(byte* buf, ulint size, bool decrypt) ...@@ -117,12 +118,12 @@ log_crypt(byte* buf, ulint size, bool decrypt)
compile_time_assert(sizeof(uint32_t) == 4); compile_time_assert(sizeof(uint32_t) == 4);
#define LOG_CRYPT_HDR_SIZE 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; 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) uint32_t dst[(OS_FILE_LOG_BLOCK_SIZE - LOG_CRYPT_HDR_SIZE)
/ sizeof(uint32_t)]; / sizeof(uint32_t)];
const ulint log_block_no = log_block_get_hdr_no(buf);
/* The log block number is not encrypted. */ /* The log block number is not encrypted. */
*aes_ctr_iv = *aes_ctr_iv =
...@@ -137,10 +138,10 @@ log_crypt(byte* buf, ulint size, bool decrypt) ...@@ -137,10 +138,10 @@ log_crypt(byte* buf, ulint size, bool decrypt)
# error "LOG_BLOCK_HDR_NO has been moved; redo log format affected!" # error "LOG_BLOCK_HDR_NO has been moved; redo log format affected!"
#endif #endif
aes_ctr_iv[1] = info.crypt_nonce.word; aes_ctr_iv[1] = info.crypt_nonce.word;
mach_write_to_8(reinterpret_cast<byte*>(aes_ctr_iv + 2), mach_write_to_8(reinterpret_cast<byte*>(aes_ctr_iv + 2), lsn);
log_block_get_start_lsn( ut_ad(log_block_get_start_lsn(lsn,
decrypt ? srv_start_lsn : log_sys->lsn, log_block_get_hdr_no(buf))
log_block_no)); == lsn);
int rc = encryption_crypt( int rc = encryption_crypt(
buf + LOG_CRYPT_HDR_SIZE, sizeof dst, buf + LOG_CRYPT_HDR_SIZE, sizeof dst,
...@@ -206,7 +207,11 @@ init_crypt_key(crypt_info_t* info, bool upgrade = false) ...@@ -206,7 +207,11 @@ init_crypt_key(crypt_info_t* info, bool upgrade = false)
return true; 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 */ @return whether the operation succeeded */
UNIV_INTERN UNIV_INTERN
bool bool
......
...@@ -997,10 +997,6 @@ log_group_write_buf( ...@@ -997,10 +997,6 @@ log_group_write_buf(
|| log_block_get_hdr_no(buf) || log_block_get_hdr_no(buf)
== log_block_convert_lsn_to_no(start_lsn)); == 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 /* Calculate the checksums for each log block and write them to
the trailer fields of the log blocks */ the trailer fields of the log blocks */
...@@ -1264,6 +1260,12 @@ log_write_up_to( ...@@ -1264,6 +1260,12 @@ log_write_up_to(
::memset(write_buf + area_end, 0, pad_size); ::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 */ /* Do the write to the log files */
log_group_write_buf( log_group_write_buf(
&log_sys->log, write_buf + area_start, &log_sys->log, write_buf + area_start,
......
...@@ -715,7 +715,8 @@ log_group_read_log_seg( ...@@ -715,7 +715,8 @@ log_group_read_log_seg(
} }
if (group->is_encrypted()) { 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) ...@@ -1016,6 +1017,7 @@ recv_find_max_checkpoint(ulint* max_field)
buf + LOG_CHECKPOINT_LSN); buf + LOG_CHECKPOINT_LSN);
group->lsn_offset = mach_read_from_8( group->lsn_offset = mach_read_from_8(
buf + LOG_CHECKPOINT_OFFSET); buf + LOG_CHECKPOINT_OFFSET);
log_sys->next_checkpoint_no = checkpoint_no;
} }
} }
......
...@@ -2223,14 +2223,6 @@ innobase_start_or_create_for_mysql() ...@@ -2223,14 +2223,6 @@ innobase_start_or_create_for_mysql()
recv_sys->dblwr.pages.clear(); 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) { if (err == DB_SUCCESS) {
/* Initialize the change buffer. */ /* Initialize the change buffer. */
err = dict_boot(); err = dict_boot();
...@@ -2733,13 +2725,6 @@ innobase_start_or_create_for_mysql() ...@@ -2733,13 +2725,6 @@ innobase_start_or_create_for_mysql()
fil_crypt_threads_init(); fil_crypt_threads_init();
fil_system_exit(); 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. */ /* Initialize online defragmentation. */
btr_defragment_init(); btr_defragment_init();
btr_defragment_thread_active = true; btr_defragment_thread_active = true;
......
...@@ -619,6 +619,7 @@ trx_free_prepared( ...@@ -619,6 +619,7 @@ trx_free_prepared(
|| (trx_state_eq(trx, TRX_STATE_ACTIVE) || (trx_state_eq(trx, TRX_STATE_ACTIVE)
&& trx->is_recovered && trx->is_recovered
&& (!srv_was_started && (!srv_was_started
|| srv_operation == SRV_OPERATION_RESTORE
|| srv_read_only_mode || srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO))); || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO)));
ut_a(trx->magic_n == TRX_MAGIC_N); ut_a(trx->magic_n == TRX_MAGIC_N);
......
...@@ -402,12 +402,20 @@ analyze table t1; ...@@ -402,12 +402,20 @@ analyze table t1;
-- enable_query_log -- enable_query_log
# index_merge on first table in join # 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) explain select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4; where t0.key1=3 or t0.key2=4;
select * from t0 left join t1 on (t0.key1=t1.key1) select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4; where t0.key1=3 or t0.key2=4;
if ($index_merge_random_rows_in_EXPLAIN)
{
--replace_column 9 #
}
explain explain
select * from t0,t1 where (t0.key1=t1.key1) and ( t0.key1=3 or t0.key2=4); select * from t0,t1 where (t0.key1=t1.key1) and ( t0.key1=3 or t0.key2=4);
......
...@@ -250,8 +250,8 @@ insert into t1 select * from t0; ...@@ -250,8 +250,8 @@ insert into t1 select * from t0;
explain select * from t0 left join t1 on (t0.key1=t1.key1) explain select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4; where t0.key1=3 or t0.key2=4;
id select_type table type possible_keys key key_len ref rows Extra 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 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 2 1 SIMPLE t1 ref i1 i1 4 test.t0.key1 #
select * from t0 left join t1 on (t0.key1=t1.key1) select * from t0 left join t1 on (t0.key1=t1.key1)
where t0.key1=3 or t0.key2=4; where t0.key1=3 or t0.key2=4;
key1 key2 key3 key4 key5 key6 key7 key8 key1 key2 key3 key4 key5 key6 key7 key8 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 ...@@ -260,8 +260,8 @@ key1 key2 key3 key4 key5 key6 key7 key8 key1 key2 key3 key4 key5 key6 key7 key8
explain explain
select * from t0,t1 where (t0.key1=t1.key1) and ( t0.key1=3 or t0.key2=4); 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 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 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 2 1 SIMPLE t1 ref i1 i1 4 test.t0.key1 #
explain explain
select * from t0,t1 where (t0.key1=t1.key1) and select * from t0,t1 where (t0.key1=t1.key1) and
(t0.key1=3 or t0.key2<4) and t1.key1=2; (t0.key1=3 or t0.key2<4) and t1.key1=2;
......
...@@ -1586,7 +1586,7 @@ int json_escape(CHARSET_INFO *str_cs, ...@@ -1586,7 +1586,7 @@ int json_escape(CHARSET_INFO *str_cs,
enum json_esc_char_classes c_class; enum json_esc_char_classes c_class;
str+= c_len; 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) if ((c_len= json_cs->cset->wc_mb(json_cs, c_chr, json, json_end)) > 0)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment