mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
MDEV-18813 PROCEDURE and anonymous blocks silently ignore FETCH GROUP NEXT ROW
Part#1: moving opt_if_not_exists from "sf_tail" and "sp_tail" to "create".
This commit is contained in:
@@ -5168,6 +5168,19 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
sp_head::check_standalone_routine_end_name(const sp_name *end_name) const
|
||||||
|
{
|
||||||
|
if (end_name && !end_name->eq(this))
|
||||||
|
{
|
||||||
|
my_error(ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0),
|
||||||
|
ErrConvDQName(end_name).ptr(), ErrConvDQName(this).ptr());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ulong sp_head::sp_cache_version() const
|
ulong sp_head::sp_cache_version() const
|
||||||
{
|
{
|
||||||
return m_parent ? m_parent->sp_cache_version() : m_sp_cache_version;
|
return m_parent ? m_parent->sp_cache_version() : m_sp_cache_version;
|
||||||
|
@@ -412,6 +412,7 @@ public:
|
|||||||
const LEX_CSTRING *field_name,
|
const LEX_CSTRING *field_name,
|
||||||
Item *val, LEX *lex);
|
Item *val, LEX *lex);
|
||||||
bool check_package_routine_end_name(const LEX_CSTRING &end_name) const;
|
bool check_package_routine_end_name(const LEX_CSTRING &end_name) const;
|
||||||
|
bool check_standalone_routine_end_name(const sp_name *end_name) const;
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
Generate a code to set a single cursor parameter variable.
|
Generate a code to set a single cursor parameter variable.
|
||||||
|
@@ -6532,6 +6532,14 @@ bool LEX::sp_body_finalize_procedure(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::sp_body_finalize_procedure_standalone(THD *thd,
|
||||||
|
const sp_name *end_name)
|
||||||
|
{
|
||||||
|
return sp_body_finalize_procedure(thd) ||
|
||||||
|
sphead->check_standalone_routine_end_name(end_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LEX::sp_body_finalize_function(THD *thd)
|
bool LEX::sp_body_finalize_function(THD *thd)
|
||||||
{
|
{
|
||||||
if (sphead->is_not_allowed_in_function("function"))
|
if (sphead->is_not_allowed_in_function("function"))
|
||||||
@@ -6548,6 +6556,14 @@ bool LEX::sp_body_finalize_function(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::sp_body_finalize_function_standalone(THD *thd,
|
||||||
|
const sp_name *end_name)
|
||||||
|
{
|
||||||
|
return sp_body_finalize_function(thd) ||
|
||||||
|
sphead->check_standalone_routine_end_name(end_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LEX::sp_block_with_exceptions_finalize_declarations(THD *thd)
|
bool LEX::sp_block_with_exceptions_finalize_declarations(THD *thd)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@@ -3737,16 +3737,10 @@ public:
|
|||||||
sp_head *make_sp_head(THD *thd, const sp_name *name, const Sp_handler *sph);
|
sp_head *make_sp_head(THD *thd, const sp_name *name, const Sp_handler *sph);
|
||||||
sp_head *make_sp_head_no_recursive(THD *thd, const sp_name *name,
|
sp_head *make_sp_head_no_recursive(THD *thd, const sp_name *name,
|
||||||
const Sp_handler *sph);
|
const Sp_handler *sph);
|
||||||
sp_head *make_sp_head_no_recursive(THD *thd,
|
|
||||||
DDL_options_st options, sp_name *name,
|
|
||||||
const Sp_handler *sph)
|
|
||||||
{
|
|
||||||
if (add_create_options_with_check(options))
|
|
||||||
return NULL;
|
|
||||||
return make_sp_head_no_recursive(thd, name, sph);
|
|
||||||
}
|
|
||||||
bool sp_body_finalize_function(THD *);
|
bool sp_body_finalize_function(THD *);
|
||||||
bool sp_body_finalize_procedure(THD *);
|
bool sp_body_finalize_procedure(THD *);
|
||||||
|
bool sp_body_finalize_function_standalone(THD *, const sp_name *end_name);
|
||||||
|
bool sp_body_finalize_procedure_standalone(THD *, const sp_name *end_name);
|
||||||
sp_package *create_package_start(THD *thd,
|
sp_package *create_package_start(THD *thd,
|
||||||
enum_sql_command command,
|
enum_sql_command command,
|
||||||
const Sp_handler *sph,
|
const Sp_handler *sph,
|
||||||
@@ -4486,6 +4480,28 @@ public:
|
|||||||
|
|
||||||
void stmt_purge_to(const LEX_CSTRING &to);
|
void stmt_purge_to(const LEX_CSTRING &to);
|
||||||
bool stmt_purge_before(Item *item);
|
bool stmt_purge_before(Item *item);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool stmt_create_routine_start(const DDL_options_st &options)
|
||||||
|
{
|
||||||
|
create_info.set(options);
|
||||||
|
return main_select_push() || check_create_options(options);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
bool stmt_create_function_start(const DDL_options_st &options)
|
||||||
|
{
|
||||||
|
sql_command= SQLCOM_CREATE_SPFUNCTION;
|
||||||
|
return stmt_create_routine_start(options);
|
||||||
|
}
|
||||||
|
bool stmt_create_procedure_start(const DDL_options_st &options)
|
||||||
|
{
|
||||||
|
sql_command= SQLCOM_CREATE_PROCEDURE;
|
||||||
|
return stmt_create_routine_start(options);
|
||||||
|
}
|
||||||
|
void stmt_create_routine_finalize()
|
||||||
|
{
|
||||||
|
pop_select(); // main select
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2841,15 +2841,14 @@ create:
|
|||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->pop_select(); //main select
|
||||||
}
|
}
|
||||||
| create_or_replace definer_opt PROCEDURE_SYM
|
| create_or_replace definer_opt PROCEDURE_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_procedure_start($1 | $4))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
sp_tail
|
sp_tail
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace definer_opt EVENT_SYM
|
| create_or_replace definer_opt EVENT_SYM
|
||||||
{
|
{
|
||||||
@@ -2861,45 +2860,41 @@ create:
|
|||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->pop_select(); //main select
|
||||||
}
|
}
|
||||||
| create_or_replace definer FUNCTION_SYM
|
| create_or_replace definer FUNCTION_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_function_start($1 | $4))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
sf_tail
|
sf_tail
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace definer AGGREGATE_SYM FUNCTION_SYM
|
| create_or_replace definer AGGREGATE_SYM FUNCTION_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_function_start($1 | $5))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
sf_tail_aggregate
|
sf_tail_aggregate
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace no_definer FUNCTION_SYM
|
| create_or_replace no_definer FUNCTION_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_function_start($1 | $4))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
create_function_tail
|
create_function_tail
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM
|
| create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_function_start($1 | $5))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
create_aggregate_function_tail
|
create_aggregate_function_tail
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace USER_SYM opt_if_not_exists clear_privileges
|
| create_or_replace USER_SYM opt_if_not_exists clear_privileges
|
||||||
grant_list opt_require_clause opt_resource_options opt_account_locking opt_password_expiration
|
grant_list opt_require_clause opt_resource_options opt_account_locking opt_password_expiration
|
||||||
@@ -17744,18 +17739,15 @@ trigger_tail:
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
udf_tail:
|
udf_tail:
|
||||||
opt_if_not_exists ident
|
ident RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
|
||||||
RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
|
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
if (unlikely(lex->add_create_options_with_check($1)))
|
if (unlikely(is_native_function(thd, & $1)))
|
||||||
MYSQL_YYABORT;
|
my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $1.str));
|
||||||
if (unlikely(is_native_function(thd, & $2)))
|
|
||||||
my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $2.str));
|
|
||||||
lex->sql_command= SQLCOM_CREATE_FUNCTION;
|
lex->sql_command= SQLCOM_CREATE_FUNCTION;
|
||||||
lex->udf.name= $2;
|
lex->udf.name= $1;
|
||||||
lex->udf.returns= (Item_result) $4;
|
lex->udf.returns= (Item_result) $3;
|
||||||
lex->udf.dl= $6.str;
|
lex->udf.dl= $5.str;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -17777,11 +17769,9 @@ sf_return_type:
|
|||||||
;
|
;
|
||||||
|
|
||||||
sf_tail:
|
sf_tail:
|
||||||
opt_if_not_exists
|
|
||||||
sp_name
|
sp_name
|
||||||
{
|
{
|
||||||
Lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
|
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1,
|
||||||
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, $2,
|
|
||||||
&sp_handler_function)))
|
&sp_handler_function)))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
@@ -17803,10 +17793,9 @@ sf_tail:
|
|||||||
;
|
;
|
||||||
|
|
||||||
sp_tail:
|
sp_tail:
|
||||||
opt_if_not_exists sp_name
|
sp_name
|
||||||
{
|
{
|
||||||
Lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1,
|
||||||
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, $2,
|
|
||||||
&sp_handler_procedure)))
|
&sp_handler_procedure)))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
|
@@ -1564,7 +1564,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
|||||||
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
|
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa
|
||||||
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
opt_field_or_var_spec fields_or_vars opt_load_data_set_spec
|
||||||
view_list_opt view_list view_select
|
view_list_opt view_list view_select
|
||||||
trigger_tail sp_tail sf_tail event_tail
|
trigger_tail event_tail
|
||||||
udf_tail
|
udf_tail
|
||||||
create_function_tail_standalone
|
create_function_tail_standalone
|
||||||
create_aggregate_function_tail_standalone
|
create_aggregate_function_tail_standalone
|
||||||
@@ -2362,15 +2362,14 @@ create:
|
|||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->pop_select(); //main select
|
||||||
}
|
}
|
||||||
| create_or_replace definer_opt PROCEDURE_SYM
|
| create_or_replace definer_opt PROCEDURE_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_procedure_start($1 | $4))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
sp_tail_standalone
|
sp_tail_standalone
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace definer_opt EVENT_SYM
|
| create_or_replace definer_opt EVENT_SYM
|
||||||
{
|
{
|
||||||
@@ -2382,45 +2381,41 @@ create:
|
|||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->pop_select(); //main select
|
||||||
}
|
}
|
||||||
| create_or_replace definer FUNCTION_SYM
|
| create_or_replace definer FUNCTION_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_function_start($1 | $4))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
sf_tail_standalone
|
sf_tail_standalone
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace definer AGGREGATE_SYM FUNCTION_SYM
|
| create_or_replace definer AGGREGATE_SYM FUNCTION_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_function_start($1 | $5))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
sf_tail_aggregate_standalone
|
sf_tail_aggregate_standalone
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace no_definer FUNCTION_SYM
|
| create_or_replace no_definer FUNCTION_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_function_start($1 | $4))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
create_function_tail_standalone
|
create_function_tail_standalone
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM
|
| create_or_replace no_definer AGGREGATE_SYM FUNCTION_SYM opt_if_not_exists
|
||||||
{
|
{
|
||||||
if (Lex->main_select_push())
|
if (Lex->stmt_create_function_start($1 | $5))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
Lex->create_info.set($1);
|
|
||||||
}
|
}
|
||||||
create_aggregate_function_tail_standalone
|
create_aggregate_function_tail_standalone
|
||||||
{
|
{
|
||||||
Lex->pop_select(); //main select
|
Lex->stmt_create_routine_finalize();
|
||||||
}
|
}
|
||||||
| create_or_replace USER_SYM opt_if_not_exists clear_privileges
|
| create_or_replace USER_SYM opt_if_not_exists clear_privileges
|
||||||
grant_list opt_require_clause opt_resource_options opt_account_locking opt_password_expiration
|
grant_list opt_require_clause opt_resource_options opt_account_locking opt_password_expiration
|
||||||
@@ -17952,18 +17947,15 @@ trigger_tail:
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
udf_tail:
|
udf_tail:
|
||||||
opt_if_not_exists ident
|
ident RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
|
||||||
RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys
|
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
if (unlikely(lex->add_create_options_with_check($1)))
|
if (unlikely(is_native_function(thd, & $1)))
|
||||||
MYSQL_YYABORT;
|
my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $1.str));
|
||||||
if (unlikely(is_native_function(thd, & $2)))
|
|
||||||
my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $2.str));
|
|
||||||
lex->sql_command= SQLCOM_CREATE_FUNCTION;
|
lex->sql_command= SQLCOM_CREATE_FUNCTION;
|
||||||
lex->udf.name= $2;
|
lex->udf.name= $1;
|
||||||
lex->udf.returns= (Item_result) $4;
|
lex->udf.returns= (Item_result) $3;
|
||||||
lex->udf.dl= $6.str;
|
lex->udf.dl= $5.str;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -17984,12 +17976,10 @@ sf_return_type:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
sf_tail:
|
sf_tail_standalone:
|
||||||
opt_if_not_exists
|
|
||||||
sp_name
|
sp_name
|
||||||
{
|
{
|
||||||
Lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
|
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1,
|
||||||
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, $2,
|
|
||||||
&sp_handler_function)))
|
&sp_handler_function)))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
@@ -18005,17 +17995,17 @@ sf_tail:
|
|||||||
}
|
}
|
||||||
sp_tail_is
|
sp_tail_is
|
||||||
sp_body
|
sp_body
|
||||||
|
opt_sp_name
|
||||||
{
|
{
|
||||||
if (unlikely(Lex->sp_body_finalize_function(thd)))
|
if (unlikely(Lex->sp_body_finalize_function_standalone(thd, $9)))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
sp_tail:
|
sp_tail_standalone:
|
||||||
opt_if_not_exists sp_name
|
sp_name
|
||||||
{
|
{
|
||||||
Lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1,
|
||||||
if (unlikely(!Lex->make_sp_head_no_recursive(thd, $1, $2,
|
|
||||||
&sp_handler_procedure)))
|
&sp_handler_procedure)))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
@@ -18027,31 +18017,13 @@ sp_tail:
|
|||||||
}
|
}
|
||||||
sp_tail_is
|
sp_tail_is
|
||||||
sp_body
|
sp_body
|
||||||
|
opt_sp_name
|
||||||
{
|
{
|
||||||
if (unlikely(Lex->sp_body_finalize_procedure(thd)))
|
if (unlikely(Lex->sp_body_finalize_procedure_standalone(thd, $8)))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
sf_tail_standalone:
|
|
||||||
sf_tail opt_sp_name
|
|
||||||
{
|
|
||||||
if (unlikely($2 && !$2->eq(Lex->sphead)))
|
|
||||||
my_yyabort_error((ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0),
|
|
||||||
ErrConvDQName($2).ptr(),
|
|
||||||
ErrConvDQName(Lex->sphead).ptr()));
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
sp_tail_standalone:
|
|
||||||
sp_tail opt_sp_name
|
|
||||||
{
|
|
||||||
if (unlikely($2 && !$2->eq(Lex->sphead)))
|
|
||||||
my_yyabort_error((ER_END_IDENTIFIER_DOES_NOT_MATCH, MYF(0),
|
|
||||||
ErrConvDQName($2).ptr(),
|
|
||||||
ErrConvDQName(Lex->sphead).ptr()));
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
opt_package_routine_end_name:
|
opt_package_routine_end_name:
|
||||||
/* Empty */ { $$= null_clex_str; }
|
/* Empty */ { $$= null_clex_str; }
|
||||||
|
Reference in New Issue
Block a user