summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-07-25 18:42:06 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2019-07-25 18:42:06 +0300
commite9c1701e11e2441435223cc7c00c467f58aaff19 (patch)
tree6be7d0e8fe87272e1abb2704fdb9859481d8acc2 /sql
parent17794fb9aac9ca4fcb0b1e5904671a025a1b6b74 (diff)
parentf3eb82f048d342c11fc3869eca2e6faed9a4835d (diff)
downloadmariadb-git-e9c1701e11e2441435223cc7c00c467f58aaff19.tar.gz
Merge 10.3 into 10.4
Diffstat (limited to 'sql')
-rw-r--r--sql/item_func.cc6
-rw-r--r--sql/item_sum.cc11
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/mysqld.cc5
-rw-r--r--sql/rpl_mi.cc9
-rw-r--r--sql/sp_head.cc2
-rw-r--r--sql/sql_plugin.cc9
-rw-r--r--sql/sql_select.cc5
-rw-r--r--sql/sql_sequence.cc2
-rw-r--r--sql/sql_table.cc3
-rw-r--r--sql/table.cc6
-rw-r--r--sql/temporary_tables.cc86
-rw-r--r--sql/wsrep_mysqld.cc37
-rw-r--r--sql/wsrep_mysqld.h18
-rw-r--r--sql/wsrep_thd.cc9
-rw-r--r--sql/wsrep_var.cc18
16 files changed, 148 insertions, 80 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 46fdbd2a4a1..bbe711791e6 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6769,9 +6769,9 @@ longlong Item_func_lastval::val_int()
/*
Sets next value to be returned from sequences
- SELECT setval('foo', 42, 0); Next nextval will return 43
- SELECT setval('foo', 42, 0, true); Same as above
- SELECT setval('foo', 42, 0, false); Next nextval will return 42
+ SELECT setval(foo, 42, 0); Next nextval will return 43
+ SELECT setval(foo, 42, 0, true); Same as above
+ SELECT setval(foo, 42, 0, false); Next nextval will return 42
*/
longlong Item_func_setval::val_int()
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 4051ae461ee..deff97e4802 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3055,11 +3055,14 @@ Item_sum_hybrid::min_max_update_str_field()
if (!args[0]->null_value)
{
- result_field->val_str(&cmp->value2);
-
- if (result_field->is_null() ||
- (cmp_sign * sortcmp(res_str,&cmp->value2,collation.collation)) < 0)
+ if (result_field->is_null())
result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
+ else
+ {
+ result_field->val_str(&cmp->value2);
+ if ((cmp_sign * sortcmp(res_str,&cmp->value2,collation.collation)) < 0)
+ result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
+ }
result_field->set_notnull();
}
DBUG_VOID_RETURN;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 350c6c30c18..060c4592a74 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -292,7 +292,7 @@ class Write_on_release_cache
public:
enum flag
{
- FLUSH_F
+ FLUSH_F= 1
};
typedef unsigned short flag_set;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 0e6070b26df..ae6334014a7 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -5801,6 +5801,9 @@ int mysqld_main(int argc, char **argv)
{
wsrep_init_startup (false);
}
+
+ WSREP_DEBUG("Startup creating %ld applier threads running %lu",
+ wsrep_slave_threads - 1, wsrep_running_applier_threads);
wsrep_create_appliers(wsrep_slave_threads - 1);
}
}
@@ -7859,6 +7862,8 @@ SHOW_VAR status_vars[]= {
{"wsrep_provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR},
{"wsrep_provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR},
{"wsrep_thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH},
+ {"wsrep_applier_thread_count", (char*) &wsrep_running_applier_threads, SHOW_LONG_NOFLUSH},
+ {"wsrep_rollbacker_thread_count", (char *) &wsrep_running_rollbacker_threads, SHOW_LONG_NOFLUSH},
{"wsrep_cluster_capabilities", (char*) &wsrep_cluster_capabilities, SHOW_CHAR_PTR},
{"wsrep", (char*) &wsrep_show_status, SHOW_FUNC},
#endif
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index 509320e7a97..732edcd5bc6 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -115,15 +115,6 @@ void Master_info::wait_until_free()
Master_info::~Master_info()
{
wait_until_free();
-#ifdef WITH_WSREP
- /*
- Do not free "wsrep" rpl_filter. It will eventually be freed by
- free_all_rpl_filters() when server terminates.
- */
- if (strncmp(connection_name.str, STRING_WITH_LEN("wsrep")))
-#endif
- rpl_filters.delete_element(connection_name.str, connection_name.length,
- (void (*)(const char*, uchar*)) free_rpl_filter);
my_free(const_cast<char*>(connection_name.str));
delete_dynamic(&ignore_server_ids);
mysql_mutex_destroy(&run_lock);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 48bd8ac8221..dfbfde64029 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -147,7 +147,7 @@ sp_get_flags_for_command(LEX *lex)
switch (lex->sql_command) {
case SQLCOM_SELECT:
- if (lex->result)
+ if (lex->result && !lex->analyze_stmt)
{
flags= 0; /* This is a SELECT with INTO clause */
break;
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index a5f27e2c562..4279cc25010 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -76,7 +76,7 @@ uint plugin_maturity_map[]=
{ 0, 1, 2, 3, 4, 5, 6 };
/*
- When you ad a new plugin type, add both a string and make sure that the
+ When you add a new plugin type, add both a string and make sure that the
init and deinit array are correctly updated.
*/
const LEX_CSTRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]=
@@ -3696,7 +3696,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
const LEX_CSTRING plugin_dash = { STRING_WITH_LEN("plugin-") };
size_t plugin_name_len= strlen(plugin_name);
size_t optnamelen;
- const int max_comment_len= 180;
+ const int max_comment_len= 255;
char *comment= (char *) alloc_root(mem_root, max_comment_len + 1);
char *optname;
@@ -3730,8 +3730,9 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
options[0].typelib= options[1].typelib= &global_plugin_typelib;
strxnmov(comment, max_comment_len, "Enable or disable ", plugin_name,
- " plugin. One of: ON, OFF, FORCE (don't start "
- "if the plugin fails to load).", NullS);
+ " plugin. One of: ON, OFF, FORCE (don't start if the plugin"
+ " fails to load), FORCE_PLUS_PERMANENT (like FORCE, but the"
+ " plugin can not be uninstalled).", NullS);
options[0].comment= comment;
/*
Allocate temporary space for the value of the tristate.
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 23827898160..b5bc91e599c 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -13153,7 +13153,10 @@ void JOIN_TAB::cleanup()
if (table)
{
table->file->ha_end_keyread();
- table->file->ha_index_or_rnd_end();
+ if (type == JT_FT)
+ table->file->ha_ft_end();
+ else
+ table->file->ha_index_or_rnd_end();
preread_init_done= FALSE;
if (table->pos_in_table_list &&
table->pos_in_table_list->jtbm_subselect)
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index 9f17590a315..4e8624d6360 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -176,7 +176,7 @@ void sequence_definition::store_fields(TABLE *table)
/*
- Check the sequence fields through seq_fields when createing a sequence.
+ Check the sequence fields through seq_fields when creating a sequence.
RETURN VALUES
false Success
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index efccd2226c3..1ecf7479372 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2300,7 +2300,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
for (table= tables; table; table= table->next_local)
{
bool is_trans= 0;
- bool table_creation_was_logged= 1;
+ bool table_creation_was_logged= 0;
LEX_CSTRING db= table->db;
handlerton *table_type= 0;
@@ -7669,6 +7669,7 @@ static bool mysql_inplace_alter_table(THD *thd,
if (res)
goto rollback;
+ DEBUG_SYNC(thd, "alter_table_inplace_before_lock_upgrade");
// Upgrade to EXCLUSIVE before commit.
if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
goto rollback;
diff --git a/sql/table.cc b/sql/table.cc
index c33ed3d2d3e..fa6146f4139 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -586,14 +586,14 @@ inline bool is_system_table_name(const char *name, size_t length)
SYNOPSIS
open_table_def()
- thd Thread handler
+ thd Thread handler
share Fill this with table definition
- db_flags Bit mask of the following flags: OPEN_VIEW
+ flags Bit mask of the following flags: OPEN_VIEW
NOTES
This function is called when the table definition is not cached in
table definition cache
- The data is returned in 'share', which is alloced by
+ The data is returned in 'share', which is allocated by
alloc_table_share().. The code assumes that share is initialized.
*/
diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc
index c42b6138c28..b39423e9131 100644
--- a/sql/temporary_tables.cc
+++ b/sql/temporary_tables.cc
@@ -1339,6 +1339,7 @@ bool THD::log_events_and_free_tmp_shares()
my_thread_id save_pseudo_thread_id= variables.pseudo_thread_id;
char db_buf[FN_REFLEN];
String db(db_buf, sizeof(db_buf), system_charset_info);
+ bool at_least_one_create_logged;
/*
Set pseudo_thread_id to be that of the processed table.
@@ -1356,7 +1357,7 @@ bool THD::log_events_and_free_tmp_shares()
within the sublist of common pseudo_thread_id to create single
DROP query.
*/
- for (;
+ for (at_least_one_create_logged= false;
share && IS_USER_TABLE(share) &&
tmpkeyval(share) == variables.pseudo_thread_id &&
share->db.length == db.length() &&
@@ -1364,51 +1365,58 @@ bool THD::log_events_and_free_tmp_shares()
/* Get the next TABLE_SHARE in the list. */
share= temporary_tables->pop_front())
{
- /*
- We are going to add ` around the table names and possible more
- due to special characters.
- */
- append_identifier(this, &s_query, &share->table_name);
- s_query.append(',');
+ if (share->table_creation_was_logged)
+ {
+ at_least_one_create_logged= true;
+ /*
+ We are going to add ` around the table names and possible more
+ due to special characters.
+ */
+ append_identifier(this, &s_query, &share->table_name);
+ s_query.append(',');
+ }
rm_temporary_table(share->db_type(), share->path.str);
free_table_share(share);
my_free(share);
}
- clear_error();
- CHARSET_INFO *cs_save= variables.character_set_client;
- variables.character_set_client= system_charset_info;
- thread_specific_used= true;
-
- Query_log_event qinfo(this, s_query.ptr(),
- s_query.length() - 1 /* to remove trailing ',' */,
- false, true, false, 0);
- qinfo.db= db.ptr();
- qinfo.db_len= db.length();
- variables.character_set_client= cs_save;
-
- get_stmt_da()->set_overwrite_status(true);
- transaction.stmt.mark_dropped_temp_table();
- bool error2= mysql_bin_log.write(&qinfo);
- if (unlikely(error|= error2))
+ if (at_least_one_create_logged)
{
- /*
- If we're here following THD::cleanup, thence the connection
- has been closed already. So lets print a message to the
- error log instead of pushing yet another error into the
- stmt_da.
-
- Also, we keep the error flag so that we propagate the error
- up in the stack. This way, if we're the SQL thread we notice
- that THD::close_tables failed. (Actually, the SQL
- thread only calls THD::close_tables while applying
- old Start_log_event_v3 events.)
- */
- sql_print_error("Failed to write the DROP statement for "
- "temporary tables to binary log");
- }
+ clear_error();
+ CHARSET_INFO *cs_save= variables.character_set_client;
+ variables.character_set_client= system_charset_info;
+ thread_specific_used= true;
+
+ Query_log_event qinfo(this, s_query.ptr(),
+ s_query.length() - 1 /* to remove trailing ',' */,
+ false, true, false, 0);
+ qinfo.db= db.ptr();
+ qinfo.db_len= db.length();
+ variables.character_set_client= cs_save;
+
+ get_stmt_da()->set_overwrite_status(true);
+ transaction.stmt.mark_dropped_temp_table();
+ bool error2= mysql_bin_log.write(&qinfo);
+ if (unlikely(error|= error2))
+ {
+ /*
+ If we're here following THD::cleanup, thence the connection
+ has been closed already. So lets print a message to the
+ error log instead of pushing yet another error into the
+ stmt_da.
+
+ Also, we keep the error flag so that we propagate the error
+ up in the stack. This way, if we're the SQL thread we notice
+ that THD::close_tables failed. (Actually, the SQL
+ thread only calls THD::close_tables while applying
+ old Start_log_event_v3 events.)
+ */
+ sql_print_error("Failed to write the DROP statement for "
+ "temporary tables to binary log");
+ }
- get_stmt_da()->set_overwrite_status(false);
+ get_stmt_da()->set_overwrite_status(false);
+ }
variables.pseudo_thread_id= save_pseudo_thread_id;
thread_specific_used= save_thread_specific_used;
}
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index d61ebb047d6..0637b4db7df 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -47,6 +47,7 @@
#include <string>
#include "log_event.h"
#include <slave.h>
+#include "sql_plugin.h" /* wsrep_plugins_pre_init() */
#include <sstream>
@@ -153,7 +154,11 @@ mysql_mutex_t LOCK_wsrep_SR_pool;
mysql_mutex_t LOCK_wsrep_SR_store;
int wsrep_replaying= 0;
-ulong wsrep_running_threads= 0; // # of currently running wsrep threads
+ulong wsrep_running_threads = 0; // # of currently running wsrep
+ // # threads
+ulong wsrep_running_applier_threads = 0; // # of running applier threads
+ulong wsrep_running_rollbacker_threads = 0; // # of running
+ // # rollbacker threads
ulong my_bind_addr;
#ifdef HAVE_PSI_INTERFACE
@@ -2658,7 +2663,21 @@ void* start_wsrep_THD(void *arg)
thd->set_command(COM_SLEEP);
thd->init_for_queries();
mysql_mutex_lock(&LOCK_wsrep_slave_threads);
+
wsrep_running_threads++;
+
+ switch (thd_args->thread_type()) {
+ case WSREP_APPLIER_THREAD:
+ wsrep_running_applier_threads++;
+ break;
+ case WSREP_ROLLBACKER_THREAD:
+ wsrep_running_rollbacker_threads++;
+ break;
+ default:
+ WSREP_ERROR("Incorrect wsrep thread type: %d", thd_args->thread_type());
+ break;
+ }
+
mysql_cond_broadcast(&COND_wsrep_slave_threads);
mysql_mutex_unlock(&LOCK_wsrep_slave_threads);
@@ -2678,7 +2697,23 @@ void* start_wsrep_THD(void *arg)
delete thd_args;
mysql_mutex_lock(&LOCK_wsrep_slave_threads);
+ DBUG_ASSERT(wsrep_running_threads > 0);
wsrep_running_threads--;
+
+ switch (thd_args->thread_type()) {
+ case WSREP_APPLIER_THREAD:
+ DBUG_ASSERT(wsrep_running_applier_threads > 0);
+ wsrep_running_applier_threads--;
+ break;
+ case WSREP_ROLLBACKER_THREAD:
+ DBUG_ASSERT(wsrep_running_rollbacker_threads > 0);
+ wsrep_running_rollbacker_threads--;
+ break;
+ default:
+ WSREP_ERROR("Incorrect wsrep thread type: %d", thd_args->thread_type());
+ break;
+ }
+
WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads);
mysql_cond_broadcast(&COND_wsrep_slave_threads);
mysql_mutex_unlock(&LOCK_wsrep_slave_threads);
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 37301afa7be..844437bab95 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -93,6 +93,8 @@ extern ulong wsrep_trx_fragment_unit;
extern ulong wsrep_SR_store_type;
extern uint wsrep_ignore_apply_errors;
extern ulong wsrep_running_threads;
+extern ulong wsrep_running_applier_threads;
+extern ulong wsrep_running_rollbacker_threads;
extern bool wsrep_new_cluster;
extern bool wsrep_gtid_mode;
extern uint32 wsrep_gtid_domain_id;
@@ -393,27 +395,37 @@ void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end);
void thd_binlog_rollback_stmt(THD * thd);
void thd_binlog_trx_reset(THD * thd);
+enum wsrep_thread_type {
+ WSREP_APPLIER_THREAD=1,
+ WSREP_ROLLBACKER_THREAD=2
+};
+
typedef void (*wsrep_thd_processor_fun)(THD*, void *);
class Wsrep_thd_args
{
public:
- Wsrep_thd_args(wsrep_thd_processor_fun fun, void* args)
+ Wsrep_thd_args(wsrep_thd_processor_fun fun, void* args,
+ wsrep_thread_type thread_type)
:
fun_ (fun),
- args_(args)
+ args_ (args),
+ thread_type_ (thread_type)
{ }
wsrep_thd_processor_fun fun() { return fun_; }
void* args() { return args_; }
+ enum wsrep_thread_type thread_type() {return thread_type_;}
+
private:
Wsrep_thd_args(const Wsrep_thd_args&);
Wsrep_thd_args& operator=(const Wsrep_thd_args&);
wsrep_thd_processor_fun fun_;
- void* args_;
+ void* args_;
+ enum wsrep_thread_type thread_type_;
};
void* start_wsrep_THD(void*);
diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc
index 6173506385d..c62132b16a2 100644
--- a/sql/wsrep_thd.cc
+++ b/sql/wsrep_thd.cc
@@ -123,7 +123,8 @@ void wsrep_create_appliers(long threads)
while (wsrep_threads++ < threads)
{
- Wsrep_thd_args* args(new Wsrep_thd_args(wsrep_replication_process, 0));
+ Wsrep_thd_args* args(new Wsrep_thd_args(wsrep_replication_process, 0,
+ WSREP_APPLIER_THREAD));
if (create_wsrep_THD(args))
{
WSREP_WARN("Can't create thread to manage wsrep replication");
@@ -312,14 +313,16 @@ void wsrep_create_rollbacker()
{
if (wsrep_cluster_address && wsrep_cluster_address[0] != 0)
{
- Wsrep_thd_args* args= new Wsrep_thd_args(wsrep_rollback_process, 0);
+ Wsrep_thd_args* args= new Wsrep_thd_args(wsrep_rollback_process, 0,
+ WSREP_ROLLBACKER_THREAD);
/* create rollbacker */
if (create_wsrep_THD(args))
WSREP_WARN("Can't create thread to manage wsrep rollback");
/* create post_rollbacker */
- args= new Wsrep_thd_args(wsrep_post_rollback_process, 0);
+ args= new Wsrep_thd_args(wsrep_post_rollback_process, 0,
+ WSREP_ROLLBACKER_THREAD);
if (create_wsrep_THD(args))
WSREP_WARN("Can't create thread to manage wsrep post rollback");
}
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index de558af6abb..315cfe2c53e 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -485,6 +485,8 @@ bool wsrep_cluster_address_update (sys_var *self, THD* thd, enum_var_type type)
if (wsrep_start_replication())
{
wsrep_create_rollbacker();
+ WSREP_DEBUG("Cluster address update creating %ld applier threads running %lu",
+ wsrep_slave_threads, wsrep_running_applier_threads);
wsrep_create_appliers(wsrep_slave_threads);
}
/* locking order to be enforced is:
@@ -585,9 +587,9 @@ void wsrep_node_address_init (const char* value)
static void wsrep_slave_count_change_update ()
{
- wsrep_slave_count_change= (wsrep_slave_threads - wsrep_running_threads + 2);
- WSREP_DEBUG("Change on slave threads: New %lu old %lu difference %d",
- wsrep_slave_threads, wsrep_running_threads, wsrep_slave_count_change);
+ wsrep_slave_count_change = (wsrep_slave_threads - wsrep_running_applier_threads);
+ WSREP_DEBUG("Change on slave threads: New %ld old %lu difference %d",
+ wsrep_slave_threads, wsrep_running_applier_threads, wsrep_slave_count_change);
}
bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type)
@@ -595,8 +597,10 @@ bool wsrep_slave_threads_update (sys_var *self, THD* thd, enum_var_type type)
wsrep_slave_count_change_update();
if (wsrep_slave_count_change > 0)
{
+ WSREP_DEBUG("Creating %d applier threads, total %ld", wsrep_slave_count_change, wsrep_slave_threads);
wsrep_create_appliers(wsrep_slave_count_change);
- wsrep_slave_count_change= 0;
+ WSREP_DEBUG("Running %lu applier threads", wsrep_running_applier_threads);
+ wsrep_slave_count_change = 0;
}
return false;
}
@@ -758,8 +762,10 @@ static SHOW_VAR wsrep_status_vars[]=
{"provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR},
{"provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR},
{"provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR},
- {"wsrep_provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR},
- {"thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH}
+ {"provider_capabilities", (char*) &wsrep_provider_capabilities, SHOW_CHAR_PTR},
+ {"thread_count", (char*) &wsrep_running_threads, SHOW_LONG_NOFLUSH},
+ {"applier_thread_count", (char*)&wsrep_running_applier_threads, SHOW_LONG_NOFLUSH},
+ {"rollbacker_thread_count", (char *)&wsrep_running_rollbacker_threads, SHOW_LONG_NOFLUSH},
};
static int show_var_cmp(const void *var1, const void *var2)