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

Conflicts:
	sql/item_cmpfunc.cc
	storage/innobase/buf/buf0flu.cc
	storage/innobase/include/ut0stage.h
	storage/innobase/row/row0upd.cc
This commit is contained in:
Alexey Botchkov 2017-08-11 10:58:23 +04:00
commit 1a9e13d622
30 changed files with 231 additions and 46 deletions

View File

@ -6573,6 +6573,25 @@ Warnings:
Warning 1356 View 'test.v' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
DROP VIEW v;
#
# MDEV-13439: Database permissions are not enough to run a subquery
# with GROUP BY within a view
#
create database test_db;
use test_db;
create table t (i int);
create user foo@localhost;
grant all on test_db.* to foo@localhost;
connect con1,localhost,foo,,;
use test_db;
create view v as select * from (select i from t group by i) sq;
select * from v;
i
disconnect con1;
connection default;
use test;
drop database test_db;
drop user foo@localhost;
#
# End of 10.2 tests
#
#

View File

@ -576,6 +576,19 @@ SELECT 1 FROM t WHERE c GROUP BY b;
COMMIT;
DROP TABLE t;
#
# Bug #25793677 INNODB: FAILING ASSERTION: CLUST_TEMPL_FOR_SEC || LEN ....
#
CREATE TABLE v (
a INT,
c INT,
b CHAR(2) GENERATED ALWAYS AS (a IN (1)) VIRTUAL,
KEY(c,b(1))) charset utf8mb4;
INSERT INTO v (a,c) VALUES (1,1);
SELECT (SELECT MAX(c) FROM v);
(SELECT MAX(c) FROM v)
1
DROP TABLE v;
#
# MDEV-9255 Add generation_expression to information_schema.columns.
#
CREATE TABLE gcol_t1 (

View File

@ -537,6 +537,19 @@ SELECT 1 FROM t WHERE c GROUP BY b;
COMMIT;
DROP TABLE t;
--echo #
--echo # Bug #25793677 INNODB: FAILING ASSERTION: CLUST_TEMPL_FOR_SEC || LEN ....
--echo #
CREATE TABLE v (
a INT,
c INT,
b CHAR(2) GENERATED ALWAYS AS (a IN (1)) VIRTUAL,
KEY(c,b(1))) charset utf8mb4;
INSERT INTO v (a,c) VALUES (1,1);
SELECT (SELECT MAX(c) FROM v);
DROP TABLE v;
--echo #
--echo # MDEV-9255 Add generation_expression to information_schema.columns.
--echo #

View File

@ -0,0 +1,20 @@
CREATE DATABASE test_jfg;
CREATE DATABASE test_jfg2;
CREATE TABLE test_jfg.test (a int unsigned PRIMARY KEY) ENGINE=InnoDB;
RENAME TABLE test_jfg.test TO test_jfg2.test;
SELECT REPLACE(path,'\\','/') path
FROM INFORMATION_SCHEMA.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%';
path
./test_jfg2/test.ibd
DROP DATABASE test_jfg;
DROP DATABASE test_jfg2;
CREATE DATABASE abc_def;
CREATE DATABASE abc_def2;
CREATE TABLE abc_def.test (a int unsigned PRIMARY KEY) ENGINE=InnoDB;
RENAME TABLE abc_def.test TO abc_def2.test1;
SELECT REPLACE(path,'\\','/') path
FROM INFORMATION_SCHEMA.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%';
path
./abc_def2/test1.ibd
DROP DATABASE abc_def;
DROP DATABASE abc_def2;

View File

@ -0,0 +1,2 @@
--innodb
--innodb-sys-datafiles

View File

@ -0,0 +1,31 @@
--source include/have_innodb.inc
--source include/not_embedded.inc
CREATE DATABASE test_jfg;
CREATE DATABASE test_jfg2;
CREATE TABLE test_jfg.test (a int unsigned PRIMARY KEY) ENGINE=InnoDB;
RENAME TABLE test_jfg.test TO test_jfg2.test;
SELECT REPLACE(path,'\\','/') path
FROM INFORMATION_SCHEMA.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%';
DROP DATABASE test_jfg;
--source include/restart_mysqld.inc
DROP DATABASE test_jfg2;
CREATE DATABASE abc_def;
CREATE DATABASE abc_def2;
CREATE TABLE abc_def.test (a int unsigned PRIMARY KEY) ENGINE=InnoDB;
RENAME TABLE abc_def.test TO abc_def2.test1;
SELECT REPLACE(path,'\\','/') path
FROM INFORMATION_SCHEMA.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%';
DROP DATABASE abc_def;
--source include/restart_mysqld.inc
DROP DATABASE abc_def2;

View File

@ -3074,7 +3074,7 @@ READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_VERSION
SESSION_VALUE NULL
GLOBAL_VALUE 5.7.18
GLOBAL_VALUE 5.7.19
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE NULL
VARIABLE_SCOPE GLOBAL

View File

@ -6274,6 +6274,31 @@ DROP TABLE IF EXISTS t;
SHOW CREATE VIEW v;
DROP VIEW v;
--echo #
--echo # MDEV-13439: Database permissions are not enough to run a subquery
--echo # with GROUP BY within a view
--echo #
create database test_db;
use test_db;
create table t (i int);
create user foo@localhost;
grant all on test_db.* to foo@localhost;
--connect (con1,localhost,foo,,)
use test_db;
create view v as select * from (select i from t group by i) sq;
select * from v;
# Cleanup
--disconnect con1
--connection default
use test;
drop database test_db;
drop user foo@localhost;
--echo #
--echo # End of 10.2 tests
--echo #

View File

@ -56,7 +56,7 @@ then
fi
# Check client version
if ! $MYSQL_CLIENT --version | grep 'Distrib 10.1' >/dev/null
if ! $MYSQL_CLIENT --version | grep 'Distrib 10.' >/dev/null
then
$MYSQL_CLIENT --version >&2
wsrep_log_error "this operation requires MySQL client version 10 or newer"
@ -133,7 +133,7 @@ SET_GTID_BINLOG_STATE=""
SQL_LOG_BIN_OFF=""
# Safety check
if echo $SERVER_VERSION | grep '^10.1' > /dev/null
if echo $SERVER_VERSION | grep '^10.' > /dev/null
then
# If binary logging is enabled on the joiner node, we need to copy donor's
# gtid_binlog_state to joiner. In order to do that, a RESET MASTER must be

View File

@ -550,14 +550,14 @@ bool Arg_comparator::set_cmp_func_string()
{
func= is_owner_equal_func() ? &Arg_comparator::compare_e_json_str:
&Arg_comparator::compare_json_str;
return false;
return 0;
}
else if ((*b)->type() == Item::FUNC_ITEM &&
((Item_func *) (*b))->functype() == Item_func::JSON_EXTRACT_FUNC)
{
func= is_owner_equal_func() ? &Arg_comparator::compare_e_json_str:
&Arg_comparator::compare_str_json;
return false;
return 0;
}
}
@ -650,7 +650,6 @@ bool Arg_comparator::set_cmp_func_real()
return false;
}
bool Arg_comparator::set_cmp_func_decimal()
{
THD *thd= current_thd;

View File

@ -7630,8 +7630,11 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
/*
It is subquery in the FROM clause. VIEW set t_ref->derived after
table opening, but this function always called before table opening.
NOTE: is_derived() can't be used here because subquery in this case
the FROM clase (derived tables) can be not be marked yet.
*/
if (!t_ref->referencing_view)
if (t_ref->is_anonymous_derived_table() || t_ref->schema_table)
{
/*
If it's a temporary table created for a subquery in the FROM

View File

@ -1413,6 +1413,8 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
flags.client_long_flag= MY_TEST(thd->client_capabilities & CLIENT_LONG_FLAG);
flags.client_protocol_41= MY_TEST(thd->client_capabilities &
CLIENT_PROTOCOL_41);
flags.client_depr_eof= MY_TEST(thd->client_capabilities &
CLIENT_DEPRECATE_EOF);
/*
Protocol influences result format, so statement results in the binary
protocol (COM_EXECUTE) cannot be served to statements asking for results
@ -1443,12 +1445,13 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
flags.div_precision_increment= thd->variables.div_precincrement;
flags.default_week_format= thd->variables.default_week_format;
DBUG_PRINT("qcache", ("\
long %d, 4.1: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
long %d, 4.1: %d, eof: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
sql mode: 0x%llx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
def_week_frmt: %lu, in_trans: %d, autocommit: %d",
(int)flags.client_long_flag,
(int)flags.client_protocol_41,
(int)flags.client_depr_eof,
(int)flags.protocol_type,
(int)flags.more_results_exists,
flags.pkt_nr,
@ -1917,6 +1920,8 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
flags.client_long_flag= MY_TEST(thd->client_capabilities & CLIENT_LONG_FLAG);
flags.client_protocol_41= MY_TEST(thd->client_capabilities &
CLIENT_PROTOCOL_41);
flags.client_depr_eof= MY_TEST(thd->client_capabilities &
CLIENT_DEPRECATE_EOF);
flags.protocol_type= (unsigned int) thd->protocol->type();
flags.more_results_exists= MY_TEST(thd->server_status &
SERVER_MORE_RESULTS_EXISTS);
@ -1938,12 +1943,13 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
flags.default_week_format= thd->variables.default_week_format;
flags.lc_time_names= thd->variables.lc_time_names;
DBUG_PRINT("qcache", ("\
long %d, 4.1: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
long %d, 4.1: %d, eof: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
sql mode: 0x%llx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
def_week_frmt: %lu, in_trans: %d, autocommit: %d",
(int)flags.client_long_flag,
(int)flags.client_protocol_41,
(int)flags.client_depr_eof,
(int)flags.protocol_type,
(int)flags.more_results_exists,
flags.pkt_nr,

View File

@ -545,6 +545,7 @@ struct Query_cache_query_flags
{
unsigned int client_long_flag:1;
unsigned int client_protocol_41:1;
unsigned int client_depr_eof:1;
unsigned int protocol_type:2;
unsigned int more_results_exists:1;
unsigned int in_trans:1;

View File

@ -823,13 +823,14 @@ exit:
table->derived_select_number= first_select->select_number;
table->s->tmp_table= INTERNAL_TMP_TABLE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (derived->referencing_view)
if (derived->is_view())
table->grant= derived->grant;
else
{
DBUG_ASSERT(derived->is_derived());
DBUG_ASSERT(derived->is_anonymous_derived_table());
table->grant.privilege= SELECT_ACL;
if (derived->is_derived())
derived->grant.privilege= SELECT_ACL;
derived->grant.privilege= SELECT_ACL;
}
#endif
/* Add new temporary table to list of open derived tables */

View File

@ -6038,7 +6038,7 @@ database_corrupted:
&& fil_page_get_type(frame) == FIL_PAGE_INDEX
&& page_is_leaf(frame)) {
if (bpage && bpage->encrypted) {
if (bpage->encrypted) {
ib::warn()
<< "Table in tablespace "
<< bpage->id.space()

View File

@ -1884,8 +1884,6 @@ buf_flush_batch(
buf_pool_mutex_enter(buf_pool);
ulint count __attribute__((unused))= 0;
/* Note: The buffer pool mutex is released and reacquired within
the flush functions. */
switch (flush_type) {
@ -1902,8 +1900,7 @@ buf_flush_batch(
buf_pool_mutex_exit(buf_pool);
DBUG_PRINT("ib_buf", ("flush %u completed, %u pages",
unsigned(flush_type), unsigned(count)));
DBUG_LOG("ib_buf", "flush " << flush_type << " completed");
}
/******************************************************************//**

View File

@ -3292,15 +3292,17 @@ fil_prepare_for_truncate(
/** Reinitialize the original tablespace header with the same space id
for single tablespace
@param[in] id space id of the tablespace
@param[in] table table belongs to tablespace
@param[in] size size in blocks
@param[in] trx Transaction covering truncate */
void
fil_reinit_space_header(
ulint id,
fil_reinit_space_header_for_table(
dict_table_t* table,
ulint size,
trx_t* trx)
{
ulint id = table->space;
ut_a(!is_system_tablespace(id));
/* Invalidate in the buffer pool all pages belonging
@ -3309,6 +3311,9 @@ fil_reinit_space_header(
and the dict operation lock during the scan and aquire
it again after the buffer pool scan.*/
/* Release the lock on the indexes too. So that
they won't violate the latch ordering. */
dict_table_x_unlock_indexes(table);
row_mysql_unlock_data_dictionary(trx);
/* Lock the search latch in shared mode to prevent user
@ -3317,8 +3322,11 @@ fil_reinit_space_header(
DEBUG_SYNC_C("buffer_pool_scan");
buf_LRU_flush_or_remove_pages(id, BUF_REMOVE_ALL_NO_WRITE, 0);
btr_search_s_unlock_all();
row_mysql_lock_data_dictionary(trx);
dict_table_x_lock_indexes(table);
/* Remove all insert buffer entries for the tablespace */
ibuf_delete_for_discarded_space(id);
@ -4636,7 +4644,7 @@ fil_ibd_load(
break;
}
/* Fall through to error handling */
/* fall through */
case DB_TABLESPACE_EXISTS:
return(FIL_LOAD_INVALID);

View File

@ -15648,10 +15648,14 @@ get_foreign_key_info(
if (ref_table == NULL) {
ib::info() << "Foreign Key referenced table "
<< foreign->referenced_table_name
<< " not found for foreign table "
<< foreign->foreign_table_name;
if (!thd_test_options(
thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
ib::info()
<< "Foreign Key referenced table "
<< foreign->referenced_table_name
<< " not found for foreign table "
<< foreign->foreign_table_name;
}
} else {
dict_table_close(ref_table, TRUE, FALSE);

View File

@ -963,12 +963,12 @@ fil_prepare_for_truncate(
/** Reinitialize the original tablespace header with the same space id
for single tablespace
@param[in] id space id of the tablespace
@param[in] table table belongs to the tablespace
@param[in] size size in blocks
@param[in] trx Transaction covering truncate */
void
fil_reinit_space_header(
ulint id,
fil_reinit_space_header_for_table(
dict_table_t* table,
ulint size,
trx_t* trx);

View File

@ -41,7 +41,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 7
#define INNODB_VERSION_BUGFIX 18
#define INNODB_VERSION_BUGFIX 19
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;

View File

@ -267,12 +267,10 @@ ut_stage_alter_t::n_pk_recs_inc()
}
/** Flag either one record or one page processed, depending on the
current phase.
@param[in] inc_val flag this many units processed at once */
current phase. */
inline
void
ut_stage_alter_t::inc(
ulint inc_val __attribute__((unused)) /* = 1 */)
ut_stage_alter_t::inc(ulint)
{
if (m_progress == NULL) {
return;
@ -286,12 +284,14 @@ ut_stage_alter_t::inc(
ut_error;
case READ_PK:
m_n_pk_pages++;
#if 0 /* TODO: MySQL 5.7 PSI */
ut_ad(inc_val == 1);
/* Overall the read pk phase will read all the pages from the
PK and will do work, proportional to the number of added
indexes, thus when this is called once per read page we
increment with 1 + m_n_sort_indexes */
inc_val = 1 + m_n_sort_indexes;
#endif
break;
case SORT:
multi_factor = m_sort_multi_factor;

View File

@ -1853,6 +1853,7 @@ lock_rec_insert_by_trx_age(
return DB_SUCCESS;
}
#ifdef UNIV_DEBUG
static
bool
lock_queue_validate(
@ -1888,6 +1889,7 @@ lock_queue_validate(
}
return true;
}
#endif /* UNIV_DEBUG */
static
void

View File

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@ -2419,6 +2419,9 @@ row_log_table_apply_op(
next_mrec = mrec + rec_offs_data_size(offsets);
if (log->table->n_v_cols) {
if (next_mrec + 2 > mrec_end) {
return(NULL);
}
next_mrec += mach_read_from_2(next_mrec);
}
@ -2457,7 +2460,7 @@ row_log_table_apply_op(
rec_init_offsets_temp(mrec, new_index, offsets);
next_mrec = mrec + rec_offs_data_size(offsets) + ext_size;
if (log->table->n_v_cols) {
if (next_mrec + 2 >= mrec_end) {
if (next_mrec + 2 > mrec_end) {
return(NULL);
}

View File

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@ -1997,6 +1997,8 @@ row_merge_read_clustered_index(
goto func_exit;
}
mem_heap_empty(row_heap);
page_cur_move_to_next(cur);
stage->n_pk_recs_inc();
@ -2676,7 +2678,6 @@ write_buffers:
goto func_exit;
}
mem_heap_empty(row_heap);
if (v_heap) {
mem_heap_empty(v_heap);
}

View File

@ -4597,6 +4597,15 @@ row_rename_table_for_mysql(
&& dict_table_is_file_per_table(table)) {
/* Make a new pathname to update SYS_DATAFILES. */
char* new_path = row_make_new_pathname(table, new_name);
char* old_path = fil_space_get_first_path(table->space);
/* If old path and new path are the same means tablename
has not changed and only the database name holding the table
has changed so we need to make the complete filepath again. */
if (!dict_tables_have_same_db(old_name, new_name)) {
ut_free(new_path);
new_path = fil_make_filepath(NULL, new_name, IBD, false);
}
info = pars_info_create();
@ -4616,6 +4625,7 @@ row_rename_table_for_mysql(
"END;\n"
, FALSE, trx);
ut_free(old_path);
ut_free(new_path);
}
if (err != DB_SUCCESS) {

View File

@ -2981,8 +2981,6 @@ row_sel_field_store_in_mysql_format_func(
@param[in] field_no templ->rec_field_no or
templ->clust_rec_field_no
or templ->icp_rec_field_no
or sec field no if clust_templ_for_sec
is TRUE
@param[in] templ row template
*/
static MY_ATTRIBUTE((warn_unused_result))
@ -3141,10 +3139,6 @@ be needed in the query.
@param[in] rec_clust whether the rec in the clustered index
@param[in] index index of rec
@param[in] offsets array returned by rec_get_offsets(rec)
@param[in] clust_templ_for_sec TRUE if rec belongs to secondary index
but the prebuilt->template is in
clustered index format and it is
used only for end range comparison
@return TRUE on success, FALSE if not all columns could be retrieved */
static MY_ATTRIBUTE((warn_unused_result))
ibool

View File

@ -2018,7 +2018,7 @@ row_truncate_table_for_mysql(
space_size -= ib_vector_size(table->fts->indexes);
}
fil_reinit_space_header(table->space, space_size, trx);
fil_reinit_space_header_for_table(table, space_size, trx);
}
DBUG_EXECUTE_IF("ib_trunc_crash_with_intermediate_log_checkpoint",

View File

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@ -256,6 +256,9 @@ row_upd_check_references_constraints(
row_mysql_freeze_data_dictionary(trx);
}
DEBUG_SYNC_C_IF_THD(thr_get_trx(thr)->mysql_thd,
"foreign_constraint_check_for_insert");
for (dict_foreign_set::iterator it = table->referenced_set.begin();
it != table->referenced_set.end();
++it) {
@ -283,6 +286,34 @@ row_upd_check_references_constraints(
FALSE, FALSE, DICT_ERR_IGNORE_NONE);
}
/* dict_operation_lock is held both here
(UPDATE or DELETE with FOREIGN KEY) and by TRUNCATE
TABLE operations.
If a TRUNCATE TABLE operation is in progress,
there can be 2 possible conditions:
1) row_truncate_table_for_mysql() is not yet called.
2) Truncate releases dict_operation_lock
during eviction of pages from buffer pool
for a file-per-table tablespace.
In case of (1), truncate will wait for FK operation
to complete.
In case of (2), truncate will be rolled forward even
if it is interrupted. So if the foreign table is
undergoing a truncate, ignore the FK check. */
if (foreign_table) {
mutex_enter(&fil_system->mutex);
const fil_space_t* space = fil_space_get_by_id(
foreign_table->space);
const bool being_truncated = space
&& space->is_being_truncated;
mutex_exit(&fil_system->mutex);
if (being_truncated) {
continue;
}
}
/* NOTE that if the thread ends up waiting for a lock
we will release dict_operation_lock temporarily!
But the counter on the table protects 'foreign' from

View File

@ -621,6 +621,7 @@ sync_array_cell_print(
}
}
#ifdef UNIV_DEBUG
/******************************************************************//**
Looks for a cell with the given thread id.
@return pointer to cell or NULL if not found */
@ -648,7 +649,6 @@ sync_array_find_thread(
return(NULL); /* Not found */
}
#ifdef UNIV_DEBUG
/******************************************************************//**
Recursion step for deadlock detection.
@return TRUE if deadlock detected */

View File

@ -54,6 +54,7 @@ red-black properties:
#define ROOT(t) (t->root->left)
#define SIZEOF_NODE(t) ((sizeof(ib_rbt_node_t) + t->sizeof_value) - 1)
#if defined UNIV_DEBUG || defined IB_RBT_TESTING
/**********************************************************************//**
Verify that the keys are in order.
@return TRUE of OK. FALSE if not ordered */
@ -91,6 +92,7 @@ rbt_check_ordering(
return(TRUE);
}
#endif /* UNIV_DEBUG || IB_RBT_TESTING */
/**********************************************************************//**
Check that every path from the root to the leaves has the same count.