mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Merge 10.6 into 10.9
This commit is contained in:
@ -299,6 +299,7 @@ ENDIF()
|
|||||||
# MDEV-24629, we need it outside of ELSIFs
|
# MDEV-24629, we need it outside of ELSIFs
|
||||||
IF(RPM MATCHES "fedora")
|
IF(RPM MATCHES "fedora")
|
||||||
ALTERNATIVE_NAME("common" "mariadb-connector-c-config" ${MARIADB_CONNECTOR_C_VERSION}-1)
|
ALTERNATIVE_NAME("common" "mariadb-connector-c-config" ${MARIADB_CONNECTOR_C_VERSION}-1)
|
||||||
|
ALTERNATIVE_NAME("shared" "mariadb-connector-c" ${MARIADB_CONNECTOR_C_VERSION}-1)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
SET(PYTHON_SHEBANG "/usr/bin/python3" CACHE STRING "python shebang")
|
SET(PYTHON_SHEBANG "/usr/bin/python3" CACHE STRING "python shebang")
|
||||||
|
42
mysql-test/main/sp-memory-leak.result
Normal file
42
mysql-test/main/sp-memory-leak.result
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#
|
||||||
|
# MDEV-30680 Warning: Memory not freed: 280 on mangled query, LeakSanitizer: detected memory leaks
|
||||||
|
#
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
IF SCALAR() expected_THEN_here;
|
||||||
|
END
|
||||||
|
$$
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'expected_THEN_here;
|
||||||
|
END' at line 2
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
WHILE SCALAR() expected_DO_here;
|
||||||
|
END
|
||||||
|
$$
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'expected_DO_here;
|
||||||
|
END' at line 2
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
REPEAT SELECT 1; UNTIL SCALAR() expected_END_here;
|
||||||
|
END
|
||||||
|
$$
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'expected_END_here;
|
||||||
|
END' at line 2
|
||||||
|
#
|
||||||
|
# MDEV-31578 DECLARE CURSOR: "Memory not freed: 280 bytes lost" on syntax error
|
||||||
|
#
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
DECLARE cur CURSOR (a INT) FOR SELECT a+1;
|
||||||
|
OPEN cur(sp_followed_by_syntax_error();
|
||||||
|
CLOSE cur;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ';
|
||||||
|
CLOSE cur;
|
||||||
|
END' at line 3
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
DECLARE cur CURSOR (a INT) FOR SELECT a+1;
|
||||||
|
OPEN cur(1,sp_followed_by_syntax_error();
|
||||||
|
CLOSE cur;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ';
|
||||||
|
CLOSE cur;
|
||||||
|
END' at line 3
|
54
mysql-test/main/sp-memory-leak.test
Normal file
54
mysql-test/main/sp-memory-leak.test
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
--echo #
|
||||||
|
--echo # MDEV-30680 Warning: Memory not freed: 280 on mangled query, LeakSanitizer: detected memory leaks
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
DELIMITER $$;
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
IF SCALAR() expected_THEN_here;
|
||||||
|
END
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
|
||||||
|
|
||||||
|
DELIMITER $$;
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
WHILE SCALAR() expected_DO_here;
|
||||||
|
END
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
|
||||||
|
|
||||||
|
DELIMITER $$;
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
REPEAT SELECT 1; UNTIL SCALAR() expected_END_here;
|
||||||
|
END
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-31578 DECLARE CURSOR: "Memory not freed: 280 bytes lost" on syntax error
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
DELIMITER $$;
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
DECLARE cur CURSOR (a INT) FOR SELECT a+1;
|
||||||
|
OPEN cur(sp_followed_by_syntax_error();
|
||||||
|
CLOSE cur;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
||||||
|
|
||||||
|
DELIMITER $$;
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
BEGIN NOT ATOMIC
|
||||||
|
DECLARE cur CURSOR (a INT) FOR SELECT a+1;
|
||||||
|
OPEN cur(1,sp_followed_by_syntax_error();
|
||||||
|
CLOSE cur;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
DELIMITER ;$$
|
@ -620,20 +620,24 @@ public:
|
|||||||
restore_lex(THD *thd)
|
restore_lex(THD *thd)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("sp_head::restore_lex");
|
DBUG_ENTER("sp_head::restore_lex");
|
||||||
|
/*
|
||||||
|
There is no a need to free the current thd->lex here.
|
||||||
|
- In the majority of the cases restore_lex() is called
|
||||||
|
on success and thd->lex does not need to be deleted.
|
||||||
|
- In cases when restore_lex() is called on error,
|
||||||
|
e.g. from sp_create_assignment_instr(), thd->lex is
|
||||||
|
already linked to some sp_instr_xxx (using sp_lex_keeper).
|
||||||
|
|
||||||
|
Note, we don't get to here in case of a syntax error
|
||||||
|
when the current thd->lex is not yet completely
|
||||||
|
initialized and linked. It gets automatically deleted
|
||||||
|
by the Bison %destructor in sql_yacc.yy.
|
||||||
|
*/
|
||||||
LEX *oldlex= (LEX *) m_lex.pop();
|
LEX *oldlex= (LEX *) m_lex.pop();
|
||||||
if (!oldlex)
|
if (!oldlex)
|
||||||
DBUG_RETURN(false); // Nothing to restore
|
DBUG_RETURN(false); // Nothing to restore
|
||||||
LEX *sublex= thd->lex;
|
|
||||||
// This restores thd->lex and thd->stmt_lex
|
// This restores thd->lex and thd->stmt_lex
|
||||||
if (thd->restore_from_local_lex_to_old_lex(oldlex))
|
DBUG_RETURN(thd->restore_from_local_lex_to_old_lex(oldlex));
|
||||||
DBUG_RETURN(true);
|
|
||||||
if (!sublex->sp_lex_in_use)
|
|
||||||
{
|
|
||||||
sublex->sphead= NULL;
|
|
||||||
lex_end(sublex);
|
|
||||||
delete sublex;
|
|
||||||
}
|
|
||||||
DBUG_RETURN(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -486,11 +486,15 @@ bool sp_create_assignment_instr(THD *thd, bool no_lookahead,
|
|||||||
be deleted by the destructor ~sp_instr_xxx().
|
be deleted by the destructor ~sp_instr_xxx().
|
||||||
So we should remove "lex" from the stack sp_head::m_lex,
|
So we should remove "lex" from the stack sp_head::m_lex,
|
||||||
to avoid double free.
|
to avoid double free.
|
||||||
Note, in case "lex" is not owned by any sp_instr_xxx,
|
|
||||||
it's also safe to remove it from the stack right now.
|
|
||||||
So we can remove it unconditionally, without testing lex->sp_lex_in_use.
|
|
||||||
*/
|
*/
|
||||||
lex->sphead->restore_lex(thd);
|
lex->sphead->restore_lex(thd);
|
||||||
|
/*
|
||||||
|
No needs for "delete lex" here: "lex" is already linked
|
||||||
|
to the sp_instr_stmt (using sp_lex_keeper) instance created by
|
||||||
|
the call for new_sp_instr_stmt() above. It will be freed
|
||||||
|
by ~sp_head/~sp_instr/~sp_lex_keeper during THD::end_statement().
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(lex->sp_lex_in_use); // used by sp_instr_stmt
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
enum_var_type inner_option_type= lex->option_type;
|
enum_var_type inner_option_type= lex->option_type;
|
||||||
@ -6831,7 +6835,6 @@ bool LEX::sp_for_loop_implicit_cursor_statement(THD *thd,
|
|||||||
if (unlikely(!(bounds->m_index=
|
if (unlikely(!(bounds->m_index=
|
||||||
new (thd->mem_root) sp_assignment_lex(thd, this))))
|
new (thd->mem_root) sp_assignment_lex(thd, this))))
|
||||||
return true;
|
return true;
|
||||||
bounds->m_index->sp_lex_in_use= true;
|
|
||||||
sphead->reset_lex(thd, bounds->m_index);
|
sphead->reset_lex(thd, bounds->m_index);
|
||||||
DBUG_ASSERT(thd->lex != this);
|
DBUG_ASSERT(thd->lex != this);
|
||||||
/*
|
/*
|
||||||
|
@ -3471,6 +3471,12 @@ public:
|
|||||||
sp_head *sphead;
|
sp_head *sphead;
|
||||||
sp_name *spname;
|
sp_name *spname;
|
||||||
|
|
||||||
|
void delete_if_not_sp_lex_in_use()
|
||||||
|
{
|
||||||
|
if (!sp_lex_in_use)
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
sp_pcontext *spcont;
|
sp_pcontext *spcont;
|
||||||
|
|
||||||
st_sp_chistics sp_chistics;
|
st_sp_chistics sp_chistics;
|
||||||
|
@ -10406,6 +10406,15 @@ bool parse_sql(THD *thd, Parser_state *parser_state,
|
|||||||
|
|
||||||
bool mysql_parse_status= thd->variables.sql_mode & MODE_ORACLE
|
bool mysql_parse_status= thd->variables.sql_mode & MODE_ORACLE
|
||||||
? ORAparse(thd) : MYSQLparse(thd);
|
? ORAparse(thd) : MYSQLparse(thd);
|
||||||
|
|
||||||
|
if (mysql_parse_status)
|
||||||
|
/*
|
||||||
|
Restore the original LEX if it was replaced when parsing
|
||||||
|
a stored procedure. We must ensure that a parsing error
|
||||||
|
does not leave any side effects in the THD.
|
||||||
|
*/
|
||||||
|
LEX::cleanup_lex_after_parse_error(thd);
|
||||||
|
|
||||||
DBUG_ASSERT(opt_bootstrap || mysql_parse_status ||
|
DBUG_ASSERT(opt_bootstrap || mysql_parse_status ||
|
||||||
thd->lex->select_stack_top == 0);
|
thd->lex->select_stack_top == 0);
|
||||||
thd->lex->current_select= thd->lex->first_select_lex();
|
thd->lex->current_select= thd->lex->first_select_lex();
|
||||||
|
@ -99,7 +99,6 @@ int yylex(void *yylval, void *yythd);
|
|||||||
#define MYSQL_YYABORT \
|
#define MYSQL_YYABORT \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
LEX::cleanup_lex_after_parse_error(thd); \
|
|
||||||
YYABORT; \
|
YYABORT; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -150,13 +149,6 @@ static Item* escape(THD *thd)
|
|||||||
|
|
||||||
static void yyerror(THD *thd, const char *s)
|
static void yyerror(THD *thd, const char *s)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
Restore the original LEX if it was replaced when parsing
|
|
||||||
a stored procedure. We must ensure that a parsing error
|
|
||||||
does not leave any side effects in the THD.
|
|
||||||
*/
|
|
||||||
LEX::cleanup_lex_after_parse_error(thd);
|
|
||||||
|
|
||||||
/* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
|
/* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */
|
||||||
if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
|
if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0)
|
||||||
s= ER_THD(thd, ER_SYNTAX_ERROR);
|
s= ER_THD(thd, ER_SYNTAX_ERROR);
|
||||||
@ -1554,6 +1546,19 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
%type <expr_lex>
|
%type <expr_lex>
|
||||||
expr_lex
|
expr_lex
|
||||||
|
|
||||||
|
%destructor
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
In case of a syntax/oom error let's free the sp_expr_lex
|
||||||
|
instance, but only if it has not been linked to any structures
|
||||||
|
such as sp_instr_jump_if_not::m_lex_keeper yet, e.g.:
|
||||||
|
IF f1() THEN1
|
||||||
|
i.e. THEN1 came instead of the expected THEN causing a syntax error.
|
||||||
|
*/
|
||||||
|
if (!$$->sp_lex_in_use)
|
||||||
|
delete $$;
|
||||||
|
} <expr_lex>
|
||||||
|
|
||||||
%type <assignment_lex>
|
%type <assignment_lex>
|
||||||
assignment_source_lex
|
assignment_source_lex
|
||||||
assignment_source_expr
|
assignment_source_expr
|
||||||
@ -1563,6 +1568,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
cursor_actual_parameters
|
cursor_actual_parameters
|
||||||
opt_parenthesized_cursor_actual_parameters
|
opt_parenthesized_cursor_actual_parameters
|
||||||
|
|
||||||
|
%destructor
|
||||||
|
{
|
||||||
|
if ($$)
|
||||||
|
{
|
||||||
|
sp_assignment_lex *elem;
|
||||||
|
List_iterator<sp_assignment_lex> li(*$$);
|
||||||
|
while ((elem= li++))
|
||||||
|
{
|
||||||
|
if (!elem->sp_lex_in_use)
|
||||||
|
delete elem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} <sp_assignment_lex_list>
|
||||||
|
|
||||||
|
|
||||||
%type <var_type>
|
%type <var_type>
|
||||||
option_type opt_var_type opt_var_ident_type
|
option_type opt_var_type opt_var_ident_type
|
||||||
|
|
||||||
@ -3857,7 +3877,6 @@ expr_lex:
|
|||||||
expr
|
expr
|
||||||
{
|
{
|
||||||
$$= $<expr_lex>1;
|
$$= $<expr_lex>1;
|
||||||
$$->sp_lex_in_use= true;
|
|
||||||
$$->set_item($2);
|
$$->set_item($2);
|
||||||
Lex->pop_select(); //min select
|
Lex->pop_select(); //min select
|
||||||
if (Lex->check_cte_dependencies_and_resolve_references())
|
if (Lex->check_cte_dependencies_and_resolve_references())
|
||||||
@ -3889,7 +3908,6 @@ assignment_source_expr:
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT($1 == thd->lex);
|
DBUG_ASSERT($1 == thd->lex);
|
||||||
$$= $1;
|
$$= $1;
|
||||||
$$->sp_lex_in_use= true;
|
|
||||||
$$->set_item_and_free_list($3, thd->free_list);
|
$$->set_item_and_free_list($3, thd->free_list);
|
||||||
thd->free_list= NULL;
|
thd->free_list= NULL;
|
||||||
Lex->pop_select(); //min select
|
Lex->pop_select(); //min select
|
||||||
@ -3910,7 +3928,6 @@ for_loop_bound_expr:
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT($1 == thd->lex);
|
DBUG_ASSERT($1 == thd->lex);
|
||||||
$$= $1;
|
$$= $1;
|
||||||
$$->sp_lex_in_use= true;
|
|
||||||
$$->set_item_and_free_list($3, NULL);
|
$$->set_item_and_free_list($3, NULL);
|
||||||
Lex->pop_select(); //main select
|
Lex->pop_select(); //main select
|
||||||
if (unlikely($$->sphead->restore_lex(thd)))
|
if (unlikely($$->sphead->restore_lex(thd)))
|
||||||
|
@ -362,8 +362,20 @@ static bool fil_node_open_file_low(fil_node_t *node)
|
|||||||
: OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT,
|
: OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT,
|
||||||
OS_FILE_AIO, type,
|
OS_FILE_AIO, type,
|
||||||
srv_read_only_mode, &success);
|
srv_read_only_mode, &success);
|
||||||
if (success)
|
if (node->is_open())
|
||||||
|
{
|
||||||
|
ut_ad(success);
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (!node->space->id && !srv_read_only_mode && my_disable_locking &&
|
||||||
|
os_file_lock(node->handle, node->name))
|
||||||
|
{
|
||||||
|
os_file_close(node->handle);
|
||||||
|
node->handle= OS_FILE_CLOSED;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* The following call prints an error message */
|
/* The following call prints an error message */
|
||||||
if (os_file_get_last_error(true) == EMFILE + 100 &&
|
if (os_file_get_last_error(true) == EMFILE + 100 &&
|
||||||
|
@ -243,21 +243,11 @@ mysql_mutex_t ibuf_mutex,
|
|||||||
ibuf_pessimistic_insert_mutex;
|
ibuf_pessimistic_insert_mutex;
|
||||||
|
|
||||||
/** The area in pages from which contract looks for page numbers for merge */
|
/** The area in pages from which contract looks for page numbers for merge */
|
||||||
const ulint IBUF_MERGE_AREA = 8;
|
constexpr ulint IBUF_MERGE_AREA = 8;
|
||||||
|
|
||||||
/** Inside the merge area, pages which have at most 1 per this number less
|
/** In ibuf_contract() at most this number of pages is read to memory in one
|
||||||
buffered entries compared to maximum volume that can buffered for a single
|
batch, in order to merge the entries for them in the change buffer */
|
||||||
page are merged along with the page whose buffer became full */
|
constexpr ulint IBUF_MAX_N_PAGES_MERGED = IBUF_MERGE_AREA;
|
||||||
const ulint IBUF_MERGE_THRESHOLD = 4;
|
|
||||||
|
|
||||||
/** In ibuf_contract at most this number of pages is read to memory in one
|
|
||||||
batch, in order to merge the entries for them in the insert buffer */
|
|
||||||
const ulint IBUF_MAX_N_PAGES_MERGED = IBUF_MERGE_AREA;
|
|
||||||
|
|
||||||
/** If the combined size of the ibuf trees exceeds ibuf.max_size by
|
|
||||||
this many pages, we start to contract it synchronous contract, but do
|
|
||||||
not insert */
|
|
||||||
const ulint IBUF_CONTRACT_DO_NOT_INSERT = 10;
|
|
||||||
|
|
||||||
/* TODO: how to cope with drop table if there are records in the insert
|
/* TODO: how to cope with drop table if there are records in the insert
|
||||||
buffer for the indexes of the table? Is there actually any problem,
|
buffer for the indexes of the table? Is there actually any problem,
|
||||||
@ -2005,11 +1995,11 @@ ibuf_free_excess_pages(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,pages,n_stored) \
|
# define ibuf_get_merge_page_nos(rec,mtr,ids,pages,n_stored) \
|
||||||
ibuf_get_merge_page_nos_func(contract,rec,mtr,ids,pages,n_stored)
|
ibuf_get_merge_page_nos_func(rec,mtr,ids,pages,n_stored)
|
||||||
#else /* UNIV_DEBUG */
|
#else /* UNIV_DEBUG */
|
||||||
# define ibuf_get_merge_page_nos(contract,rec,mtr,ids,pages,n_stored) \
|
# define ibuf_get_merge_page_nos(rec,mtr,ids,pages,n_stored) \
|
||||||
ibuf_get_merge_page_nos_func(contract,rec,ids,pages,n_stored)
|
ibuf_get_merge_page_nos_func(rec,ids,pages,n_stored)
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
@ -2020,10 +2010,6 @@ static
|
|||||||
ulint
|
ulint
|
||||||
ibuf_get_merge_page_nos_func(
|
ibuf_get_merge_page_nos_func(
|
||||||
/*=========================*/
|
/*=========================*/
|
||||||
ibool contract,/*!< in: TRUE if this function is called to
|
|
||||||
contract the tree, FALSE if this is called
|
|
||||||
when a single page becomes full and we look
|
|
||||||
if it pays to read also nearby pages */
|
|
||||||
const rec_t* rec, /*!< in: insert buffer record */
|
const rec_t* rec, /*!< in: insert buffer record */
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
mtr_t* mtr, /*!< in: mini-transaction holding rec */
|
mtr_t* mtr, /*!< in: mini-transaction holding rec */
|
||||||
@ -2154,22 +2140,10 @@ corruption:
|
|||||||
|| rec_page_no != prev_page_no)
|
|| rec_page_no != prev_page_no)
|
||||||
&& (prev_space_id != 0 || prev_page_no != 0)) {
|
&& (prev_space_id != 0 || prev_page_no != 0)) {
|
||||||
|
|
||||||
if (contract
|
|
||||||
|| (prev_page_no == first_page_no
|
|
||||||
&& prev_space_id == first_space_id)
|
|
||||||
|| (volume_for_page
|
|
||||||
> ((IBUF_MERGE_THRESHOLD - 1)
|
|
||||||
* 4U << srv_page_size_shift
|
|
||||||
/ IBUF_PAGE_SIZE_PER_FREE_SPACE)
|
|
||||||
/ IBUF_MERGE_THRESHOLD)) {
|
|
||||||
|
|
||||||
space_ids[*n_stored] = prev_space_id;
|
space_ids[*n_stored] = prev_space_id;
|
||||||
page_nos[*n_stored] = prev_page_no;
|
page_nos[*n_stored] = prev_page_no;
|
||||||
|
|
||||||
(*n_stored)++;
|
(*n_stored)++;
|
||||||
|
|
||||||
sum_volumes += volume_for_page;
|
sum_volumes += volume_for_page;
|
||||||
}
|
|
||||||
|
|
||||||
if (rec_space_id != first_space_id
|
if (rec_space_id != first_space_id
|
||||||
|| rec_page_no / IBUF_MERGE_AREA
|
|| rec_page_no / IBUF_MERGE_AREA
|
||||||
@ -2429,7 +2403,7 @@ tablespace_deleted:
|
|||||||
@return a lower limit for the combined size in bytes of entries which
|
@return a lower limit for the combined size in bytes of entries which
|
||||||
will be merged from ibuf trees to the pages read
|
will be merged from ibuf trees to the pages read
|
||||||
@retval 0 if ibuf.empty */
|
@retval 0 if ibuf.empty */
|
||||||
ulint ibuf_contract()
|
ATTRIBUTE_COLD ulint ibuf_contract()
|
||||||
{
|
{
|
||||||
if (UNIV_UNLIKELY(!ibuf.index)) return 0;
|
if (UNIV_UNLIKELY(!ibuf.index)) return 0;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
@ -2461,10 +2435,8 @@ ulint ibuf_contract()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ulint n_pages = 0;
|
ulint n_pages = 0;
|
||||||
sum_sizes = ibuf_get_merge_page_nos(TRUE,
|
sum_sizes = ibuf_get_merge_page_nos(btr_cur_get_rec(&cur), &mtr,
|
||||||
btr_cur_get_rec(&cur), &mtr,
|
space_ids, page_nos, &n_pages);
|
||||||
space_ids,
|
|
||||||
page_nos, &n_pages);
|
|
||||||
ibuf_mtr_commit(&mtr);
|
ibuf_mtr_commit(&mtr);
|
||||||
|
|
||||||
ibuf_read_merge_pages(space_ids, page_nos, n_pages);
|
ibuf_read_merge_pages(space_ids, page_nos, n_pages);
|
||||||
@ -2554,30 +2526,6 @@ ibuf_merge_space(
|
|||||||
return(n_pages);
|
return(n_pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
|
||||||
Contract insert buffer trees after insert if they are too big. */
|
|
||||||
UNIV_INLINE
|
|
||||||
void
|
|
||||||
ibuf_contract_after_insert(
|
|
||||||
/*=======================*/
|
|
||||||
ulint entry_size) /*!< in: size of a record which was inserted
|
|
||||||
into an ibuf tree */
|
|
||||||
{
|
|
||||||
/* dirty comparison, to avoid contention on ibuf_mutex */
|
|
||||||
if (ibuf.size < ibuf.max_size) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Contract at least entry_size many bytes */
|
|
||||||
ulint sum_sizes = 0;
|
|
||||||
ulint size;
|
|
||||||
|
|
||||||
do {
|
|
||||||
size = ibuf_contract();
|
|
||||||
sum_sizes += size;
|
|
||||||
} while (size > 0 && sum_sizes < entry_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Determine if a change buffer record has been encountered already.
|
/** Determine if a change buffer record has been encountered already.
|
||||||
@param rec change buffer record in the MySQL 5.5 format
|
@param rec change buffer record in the MySQL 5.5 format
|
||||||
@param hash hash table of encountered records
|
@param hash hash table of encountered records
|
||||||
@ -3176,10 +3124,6 @@ ibuf_insert_low(
|
|||||||
buf_block_t* block = NULL;
|
buf_block_t* block = NULL;
|
||||||
page_t* root;
|
page_t* root;
|
||||||
dberr_t err;
|
dberr_t err;
|
||||||
ibool do_merge;
|
|
||||||
uint32_t space_ids[IBUF_MAX_N_PAGES_MERGED];
|
|
||||||
uint32_t page_nos[IBUF_MAX_N_PAGES_MERGED];
|
|
||||||
ulint n_stored;
|
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
mtr_t bitmap_mtr;
|
mtr_t bitmap_mtr;
|
||||||
|
|
||||||
@ -3190,28 +3134,9 @@ ibuf_insert_low(
|
|||||||
ut_ad(page_id.space() == index->table->space_id);
|
ut_ad(page_id.space() == index->table->space_id);
|
||||||
ut_a(op < IBUF_OP_COUNT);
|
ut_a(op < IBUF_OP_COUNT);
|
||||||
|
|
||||||
do_merge = FALSE;
|
|
||||||
|
|
||||||
/* Perform dirty comparison of ibuf.max_size and ibuf.size to
|
/* Perform dirty comparison of ibuf.max_size and ibuf.size to
|
||||||
reduce ibuf_mutex contention. This should be OK; at worst we
|
reduce ibuf_mutex contention. */
|
||||||
are doing some excessive ibuf_contract() or occasionally
|
if (ibuf.size >= ibuf.max_size) {
|
||||||
skipping an ibuf_contract(). */
|
|
||||||
const ulint max_size = ibuf.max_size;
|
|
||||||
|
|
||||||
if (max_size == 0) {
|
|
||||||
return(DB_STRONG_FAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ibuf.size >= max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
|
|
||||||
/* Insert buffer is now too big, contract it but do not try
|
|
||||||
to insert */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef UNIV_IBUF_DEBUG
|
|
||||||
fputs("Ibuf too big\n", stderr);
|
|
||||||
#endif
|
|
||||||
ibuf_contract();
|
|
||||||
|
|
||||||
return(DB_STRONG_FAIL);
|
return(DB_STRONG_FAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3263,17 +3188,6 @@ func_exit:
|
|||||||
ibuf_mtr_commit(&mtr);
|
ibuf_mtr_commit(&mtr);
|
||||||
ut_free(pcur.old_rec_buf);
|
ut_free(pcur.old_rec_buf);
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
if (err == DB_SUCCESS && mode == BTR_INSERT_TREE) {
|
|
||||||
ibuf_contract_after_insert(entry_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (do_merge) {
|
|
||||||
#ifdef UNIV_IBUF_DEBUG
|
|
||||||
ut_a(n_stored <= IBUF_MAX_N_PAGES_MERGED);
|
|
||||||
#endif
|
|
||||||
ibuf_read_merge_pages(space_ids, page_nos, n_stored);
|
|
||||||
}
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3363,15 +3277,6 @@ commit_exit:
|
|||||||
bits)) {
|
bits)) {
|
||||||
/* Release the bitmap page latch early. */
|
/* Release the bitmap page latch early. */
|
||||||
ibuf_mtr_commit(&bitmap_mtr);
|
ibuf_mtr_commit(&bitmap_mtr);
|
||||||
|
|
||||||
/* It may not fit */
|
|
||||||
do_merge = TRUE;
|
|
||||||
|
|
||||||
ibuf_get_merge_page_nos(FALSE,
|
|
||||||
btr_pcur_get_rec(&pcur), &mtr,
|
|
||||||
space_ids,
|
|
||||||
page_nos, &n_stored);
|
|
||||||
|
|
||||||
goto fail_exit;
|
goto fail_exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,9 +242,11 @@ enum rec_leaf_format {
|
|||||||
REC_LEAF_INSTANT
|
REC_LEAF_INSTANT
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined __GNUC__ && !defined __clang__ && __GNUC__ < 12
|
#if defined __GNUC__ && !defined __clang__
|
||||||
# pragma GCC diagnostic push
|
# pragma GCC diagnostic push
|
||||||
# pragma GCC diagnostic ignored "-Wconversion" /* GCC 5 to 11 need this */
|
# if __GNUC__ < 12 || defined WITH_UBSAN
|
||||||
|
# pragma GCC diagnostic ignored "-Wconversion"
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
/** Determine the offset to each field in a leaf-page record
|
/** Determine the offset to each field in a leaf-page record
|
||||||
in ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED.
|
in ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED.
|
||||||
@ -1707,7 +1709,7 @@ rec_convert_dtuple_to_rec_new(
|
|||||||
REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
|
REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
#if defined __GNUC__ && !defined __clang__ && __GNUC__ < 11
|
#if defined __GNUC__ && !defined __clang__
|
||||||
# pragma GCC diagnostic pop /* ignored "-Wconversion" */
|
# pragma GCC diagnostic pop /* ignored "-Wconversion" */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@ for child3
|
|||||||
|
|
||||||
MDEV-6268 SPIDER table with no COMMENT clause causes queries to wait forever
|
MDEV-6268 SPIDER table with no COMMENT clause causes queries to wait forever
|
||||||
|
|
||||||
CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
|
CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
|
||||||
create table t2 (c int);
|
create table t2 (c int);
|
||||||
create table t1 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"';
|
create table t1 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv_self_reference_multi",TABLE "t2"';
|
||||||
create table t0 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"';
|
create table t0 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv_self_reference_multi",TABLE "t1"';
|
||||||
alter table t2 ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t0"';
|
alter table t2 ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv_self_reference_multi",TABLE "t0"';
|
||||||
select * from t0;
|
select * from t0;
|
||||||
ERROR HY000: An infinite loop is detected when opening table test.t0
|
ERROR HY000: An infinite loop is detected when opening table test.t0
|
||||||
select * from t1;
|
select * from t1;
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
--echo MDEV-6268 SPIDER table with no COMMENT clause causes queries to wait forever
|
--echo MDEV-6268 SPIDER table with no COMMENT clause causes queries to wait forever
|
||||||
--echo
|
--echo
|
||||||
|
|
||||||
--replace_regex /SOCKET ".*"/SOCKET "$MASTER_1_MYSOCK"/
|
--let $srv=srv_self_reference_multi
|
||||||
eval CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
|
evalp CREATE SERVER $srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root');
|
||||||
create table t2 (c int);
|
create table t2 (c int);
|
||||||
create table t1 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"';
|
eval create table t1 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "$srv",TABLE "t2"';
|
||||||
create table t0 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"';
|
eval create table t0 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "$srv",TABLE "t1"';
|
||||||
alter table t2 ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t0"';
|
eval alter table t2 ENGINE=Spider COMMENT='WRAPPER "mysql", srv "$srv",TABLE "t0"';
|
||||||
--error 12719
|
--error 12719
|
||||||
select * from t0;
|
select * from t0;
|
||||||
--error 12719
|
--error 12719
|
||||||
|
Reference in New Issue
Block a user