Commit 4a3f651d authored by unknown's avatar unknown

Fixed bug in send in mysqltest

Removed usage of @r/result as this made life hard when testing different
table handlers.
Allow concurrent inserts if no update/binary log.
Don't remove key_cache at flush tables.
Fixed bug in SELECT DISTINCT SUM()...


BitKeeper/deleted/.del-rpl000012.status.result~bbbd650b5beea32f:
  Delete: mysql-test/r/rpl000012.status.result
BitKeeper/deleted/.del-rpl000013.status.result~6bee190c298cc9fd:
  Delete: mysql-test/r/rpl000013.status.result
Docs/manual.texi:
  Changelog
client/mysqltest.c:
  Fixed bug in 'send' that Sasha had introduced.
  Make database, port and socket optional parameters to connect()
mysql-test/r/rpl000005.result:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/r/rpl000006.result:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/r/rpl000012.result:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/r/rpl000013.result:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/r/sel000033.result:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/backup.test:
  Use default port and socket.
mysql-test/t/dirty-close.test:
  Use default port and socket.
mysql-test/t/flush.test:
  Use default port and socket.
mysql-test/t/kill.test:
  Use default port and socket.
mysql-test/t/overflow.test:
  Use default port and socket.
mysql-test/t/rpl000003.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/rpl000005.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/rpl000006.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/rpl000007.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/rpl000008.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/rpl000009.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/rpl000010.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/rpl000011.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/rpl000012.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/rpl000013.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/sel000001.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/sel000002.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/sel000003.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/sel000031.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/sel000032.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/sel000033.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/sel000100.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/shw000001.test:
  Removed usage of @r/result as this made life hard when doing
  test for multiple table handlers.
mysql-test/t/status.test:
  Use default port and socket.
sql/gen_lex_hash.cc:
  Smaller hash table
sql/mysql_priv.h:
  Allow concurrent inserts if no update/binary log
sql/mysqld.cc:
  Allow concurrent inserts if no update/binary log
  Don't remove key_cache at flush tables
sql/sql_base.cc:
  Don't remove key_cache at flush tables
sql/sql_select.cc:
  Fix bug in SELECT DISTINCT SUM().
sql/sql_yacc.yy:
  Allow concurrent inserts if no update/binary log
tests/export.pl:
  C
parent a032242b
......@@ -36147,6 +36147,10 @@ The temporary file will be deleted when the thread ends.
The @code{max_binlog_cache_size} can be used to restrict the total size used
to cache a multi-transaction query.
If you are using the update or binary log then concurrent inserts will
not work together with @code{CREATE ... INSERT} and @code{INSERT ... SELECT}.
This is to ensure that you can recreate an exact copy of your tables by
applying a the log on a backup.
@cindex slow query log
@cindex files, slow query log
@node Slow query log, , Binary log, Log files
......@@ -42399,6 +42403,9 @@ not yet 100 % confident in this code.
Fixed that one can't use database names with @code{.}. This fixes a serious
security issue when @code{mysqld} is run as root.
@item
Don't free the key cache on @code{FLUSH TABLES} as this will cause problems
with temporary tables.
@item
Fixed a core-dump bug when using very complex query involving
@code{DISTINCT} and summary functions.
@item
......@@ -42416,6 +42423,9 @@ Fixed a bug in @code{CONCAT_WS()} where it returned wrong results.
@item
Changed @code{CREATE ... INSERT} and @code{INSERT ... SELECT} to not
allow concurrent inserts as this could make the binary log hard to repeat.
(Concurrent inserts are enabled if you are not using the binary or update log).
@item
Changed some macros to be able to use fast mutex with glibc 2.2.
@end itemize
@node News-3.23.35, News-3.23.34a, News-3.23.36, News-3.23.x
......@@ -43,7 +43,7 @@
**********************************************************************/
#define MTEST_VERSION "1.7"
#define MTEST_VERSION "1.8"
#include <global.h>
#include <my_sys.h>
......@@ -269,6 +269,7 @@ static void die(const char* fmt, ...)
fprintf(stderr, "%s: ", my_progname);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
fflush(stderr);
}
va_end(args);
free_used_memory();
......@@ -864,12 +865,11 @@ int close_connection(struct st_query* q)
char* safe_get_param(char* str, char** arg, const char* msg)
{
DBUG_ENTER("safe_get_param");
while(*str && isspace(*str)) str++;
while (*str && isspace(*str)) str++;
*arg = str;
while(*str && *str != ',' && *str != ')')
for (; *str && *str != ',' && *str != ')' ; str++)
{
if (isspace(*str)) *str = 0;
str++;
}
if (!*str)
die(msg);
......@@ -885,6 +885,7 @@ int do_connect(struct st_query* q)
*con_db, *con_sock;
char* p=q->first_argument;
char buff[FN_REFLEN];
int con_port;
DBUG_ENTER("do_connect");
DBUG_PRINT("enter",("connect: %s",p));
......@@ -896,16 +897,27 @@ int do_connect(struct st_query* q)
p = safe_get_param(p, &con_user, "missing connection user");
p = safe_get_param(p, &con_pass, "missing connection password");
p = safe_get_param(p, &con_db, "missing connection db");
if (!*p || *p == ';') /* Default port and sock */
{
con_port=port;
con_sock=(char*) unix_sock;
}
else
{
p = safe_get_param(p, &con_port_str, "missing connection port");
con_port=atoi(con_port_str);
p = safe_get_param(p, &con_sock, "missing connection socket");
}
if (next_con == cons_end)
die("Connection limit exhausted - increase MAX_CONS in mysqltest.c");
if (!mysql_init(&next_con->mysql))
die("Failed on mysql_init()");
con_sock=fn_format(buff, con_sock, TMPDIR,"",0);
con_sock=fn_format(buff, con_sock, TMPDIR, "",0);
if (!con_db[0])
con_db=db;
if (!mysql_real_connect(&next_con->mysql, con_host, con_user, con_pass,
con_db, atoi(con_port_str), con_sock, 0))
con_db, con_port, con_sock, 0))
die("Could not open connection '%s': %s", con_name,
mysql_error(&next_con->mysql));
......@@ -1572,7 +1584,7 @@ int main(int argc, char** argv)
{
int error = 0;
struct st_query* q;
my_bool require_file=0;
my_bool require_file=0, q_send_flag=0;
char save_file[FN_REFLEN];
MY_INIT(argv[0]);
......@@ -1639,6 +1651,11 @@ int main(int argc, char** argv)
* read-result only ( reap) */
if (q->type == Q_QUERY) /* for a full query, enable the send stage */
flags |= QUERY_SEND;
if (q_send_flag)
{
flags= QUERY_SEND;
q_send_flag=0;
}
if (save_file[0])
{
strmov(q->record_file,save_file);
......@@ -1649,9 +1666,14 @@ int main(int argc, char** argv)
break;
}
case Q_SEND:
if(q->query == q->query_buf) /* fix up query pointer if this is
* first iteration for this line
*/
if (!q->query[q->first_word_len])
{
/* This happens when we use 'send' on it's own line */
q_send_flag=1;
break;
}
/* fix up query pointer if this is * first iteration for this line */
if (q->query == q->query_buf)
q->query += q->first_word_len;
error |= run_query(&cur_con->mysql, q, QUERY_SEND);
/* run query can execute a query partially, depending on the flags
......
project_id project_name client_ptr comments total_budget
......@@ -2,3 +2,7 @@ name age id
Andy 31 00000001
Jacob 2 00000002
Caleb 1 00000003
name age id
Andy 31 00000001
Jacob 2 00000002
Caleb 1 00000003
unix_timestamp(t)
200006
unix_timestamp(t)
200006
......@@ -5,3 +5,5 @@ n
4
5
6
Variable_name Value
Slave_open_temp_tables 0
Variable_name Value
Slave_open_temp_tables 0
......@@ -5,3 +5,5 @@ n
4
5
6
Variable_name Value
Slave_open_temp_tables 0
Variable_name Value
Slave_open_temp_tables 0
......@@ -2,3 +2,7 @@ id
2
5
9
id
2
5
9
connect (con1,localhost,root,,test,0,mysql-master.sock);
connect (con2,localhost,root,,test,0,mysql-master.sock);
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
set SQL_LOG_BIN=0;
drop table if exists t1;
......
connect (con1,localhost,root,,test,0,mysql-master.sock);
connect (con2,localhost,root,,test,0,mysql-master.sock);
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
dirty_close con1;
connection con2;
......
connect (con1,localhost,root,,test,0,mysql-master.sock);
connect (con2,localhost,root,,test,0,mysql-master.sock);
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection con1;
drop table if exists t1;
create temporary table t1(n int not null primary key);
......
connect (con1, localhost, root,,test,0, mysql-master.sock);
connect (con2, localhost, root,,test,0, mysql-master.sock);
connect (con1, localhost, root,,);
connect (con2, localhost, root,,);
#remember id of con1
connection con1;
......
connect (con1,localhost,boo,,test,0,mysql-master.sock);
connect (con1,localhost,boo,,);
connection con1;
-- error 1064;
drop database AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
......@@ -7,7 +7,7 @@ insert into t1 values (3);
save_master_pos;
connection slave;
sync_with_master;
@r/rpl000003.result select * from t1;
select * from t1;
connection master;
drop table t1;
save_master_pos;
......
......@@ -6,11 +6,11 @@ INSERT INTO t1 SET name='Andy', age=31;
INSERT t1 SET name='Jacob', age=2;
INSERT into t1 SET name='Caleb', age=1;
ALTER TABLE t1 ADD id int(8) ZEROFILL AUTO_INCREMENT PRIMARY KEY;
@r/rpl000005.result select * from t1;
select * from t1;
save_master_pos;
connection slave;
sync_with_master;
@r/rpl000005.result select * from t1;
select * from t1;
connection master;
drop table t1;
save_master_pos;
......
......@@ -5,11 +5,11 @@ set timestamp=200006;
drop table if exists foo;
create table foo(t timestamp not null,a char(1));
insert into foo ( a) values ('F');
@r/rpl000006.result select unix_timestamp(t) from foo;
select unix_timestamp(t) from foo;
connection slave;
drop table if exists foo;
load table foo from master;
@r/rpl000006.result select unix_timestamp(t) from foo;
select unix_timestamp(t) from foo;
connection master;
drop table foo;
save_master_pos;
......
......@@ -18,7 +18,7 @@ insert into bar values(15);
save_master_pos;
connection slave;
sync_with_master;
@r/rpl000007.result select foo.n,bar.m from foo,bar;
select foo.n,bar.m from foo,bar;
connection master;
drop table if exists bar,foo;
save_master_pos;
......
......@@ -20,7 +20,7 @@ insert into choo values(55);
save_master_pos;
connection slave;
sync_with_master;
@r/rpl000008.result select foo.n,bar.m,choo.k from foo,bar,choo;
select foo.n,bar.m,choo.k from foo,bar,choo;
connection master;
drop table if exists foo,bar,choo;
save_master_pos;
......
......@@ -22,7 +22,7 @@ insert into bar.bar values(15);
save_master_pos;
connection slave;
sync_with_master;
@r/rpl000009.result select foo.foo.n,bar.bar.m from foo.foo,bar.bar;
select foo.foo.n,bar.bar.m from foo.foo,bar.bar;
connection master;
drop database if exists bar;
drop database if exists foo;
......
......@@ -11,7 +11,7 @@ insert into t1 values(2);
save_master_pos;
connection slave;
sync_with_master;
@r/rpl000010.result select n from t1;
select n from t1;
connection master;
drop table t1;
save_master_pos;
......
......@@ -15,7 +15,7 @@ save_master_pos;
connection slave;
#let slave catch up
sync_with_master;
@r/rpl000011.result select * from t1;
select * from t1;
connection master;
drop table t1;
save_master_pos;
......
......@@ -24,12 +24,12 @@ disconnect master1;
connection slave;
#same trick - make sure we catch drop of temporary table on disconnect
sync_with_master 1;
@r/rpl000012.result select * from t2;
@r/rpl000012.status.result show status like 'Slave_open_temp_tables';
select * from t2;
show status like 'Slave_open_temp_tables';
#
# Clean up
#
connect (master2,localhost,root,,test,0,mysql-master.sock);
connect (master2,localhost,root,,);
connection master2;
drop table if exists t1,t2;
save_master_pos;
......
......@@ -25,12 +25,12 @@ disconnect master1;
connection slave;
# same trick to go one more event
sync_with_master 1;
@r/rpl000013.result select * from t2;
@r/rpl000013.status.result show status like 'Slave_open_temp_tables';
select * from t2;
show status like 'Slave_open_temp_tables';
#
# Clean up
#
connect (master2,localhost,root,,test,0,mysql-master.sock);
connect (master2,localhost,root,,);
connection master2;
drop table if exists t1,t2;
save_master_pos;
......
......@@ -14,5 +14,5 @@
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (s CHAR(20) PRIMARY KEY, id INT);
INSERT INTO t1 VALUES ('cat', 1), ('mouse', 3), ('dog', 2), ('snake', 77);
@r/sel000001.result SELECT s, id FROM t1 WHERE s = 'mouse';
SELECT s, id FROM t1 WHERE s = 'mouse';
drop table t1;
......@@ -13,5 +13,5 @@
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (n INT);
INSERT INTO t1 VALUES (1), (2), (3);
@r/sel000002.result SELECT * FROM t1;
SELECT * FROM t1;
drop table t1;
......@@ -14,5 +14,5 @@
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (name CHAR(20) NOT NULL PRIMARY KEY, score SMALLINT NOT NULL, KEY(score));
INSERT INTO t1 VALUES ('Sasha', 20), ('Matt', 20), ('Monty', 10), ('David', 10), ('Tim', 10), ('Jeremy', 10);
@r/sel000003.result SELECT COUNT(*) as n, score FROM t1 GROUP BY score;
SELECT COUNT(*) as n, score FROM t1 GROUP BY score;
drop table t1;
......@@ -16,5 +16,5 @@ val int(10) not null);
insert into t1 values (1),(2),(4);
insert into t2 values (1,1),(2,1),(3,1),(4,2);
@r/sel000031.result select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
drop table t1,t2;
......@@ -16,4 +16,5 @@ val int(10) not null);
insert into t1 values (1),(2),(4);
insert into t2 values (1,1),(2,1),(3,1),(4,2);
@r/sel000032.result select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id;
select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id;
drop table t1,t2;
......@@ -13,6 +13,6 @@ drop table if exists t1;
create table t1 (id int(10) primary key);
insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
@r/sel000033.result select id from t1 where id in (2,5,9) ;
@r/sel000033.result select id from t1 where id=2 or id=5 or id=9 ;
select id from t1 where id in (2,5,9) ;
select id from t1 where id=2 or id=5 or id=9 ;
drop table t1;
......@@ -20,7 +20,7 @@ CREATE TABLE t2 (
KEY NAME (NAME)
);
@r/sel000100.result SELECT DISTINCT
SELECT DISTINCT
t2.id AS key_link_id,
t2.name AS link
FROM t1
......
......@@ -4,5 +4,5 @@ create table t1 (
test_set set( 'val1', 'val2', 'val3' ) not null default '',
name char(20) default 'O''Brien'
) comment = 'it\'s a table' ;
@r/shw000001.result show create table t1 ;
show create table t1 ;
drop table t1;
connect (con1,localhost,root,,test,0,mysql-master.sock);
connect (con2,localhost,root,,test,0,mysql-master.sock);
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
flush status;
show status like 'Table_lock%';
......
......@@ -472,7 +472,7 @@ int main(int argc,char **argv)
int error;
MY_INIT(argv[0]);
start_value=318439L; best_t1=7136932L; best_t2=1067561L; best_type=0; /* mode=5413 add=5 type: 0 */
start_value=6871391L; best_t1=1779313L; best_t2=5719807L; best_type=3; /* mode=4987 add=5 type: 0 */
if (get_options(argc,(char **) argv))
exit(1);
......
......@@ -532,7 +532,7 @@ extern ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
lower_case_table_names,thread_stack,thread_stack_min,
binlog_cache_size, max_binlog_cache_size;
extern ulong specialflag, current_pid;
extern bool low_priority_updates;
extern bool low_priority_updates, using_update_log;
extern bool opt_sql_bin_update, opt_safe_show_db;
extern char language[LIBLEN],reg_ext[FN_EXTLEN],blob_newline;
extern const char **errmesg; /* Error messages */
......
......@@ -253,7 +253,7 @@ ulong max_tmp_tables,max_heap_table_size;
ulong bytes_sent = 0L, bytes_received = 0L;
bool opt_endinfo,using_udf_functions,low_priority_updates, locked_in_memory;
bool opt_using_transactions;
bool opt_using_transactions, using_update_log;
bool volatile abort_loop,select_thread_in_use,grant_option;
bool volatile ready_to_exit,shutdown_in_progress;
ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */
......@@ -649,7 +649,7 @@ void clean_up(void)
if (!opt_noacl)
udf_free();
#endif
end_key_cache(); /* This is usually freed automaticly */
end_key_cache();
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
#ifdef USE_RAID
end_raid();
......@@ -1683,8 +1683,11 @@ int main(int argc, char **argv)
if (opt_log)
open_log(&mysql_log, glob_hostname, opt_logname, ".log", LOG_NORMAL);
if (opt_update_log)
{
open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
LOG_NEW);
using_update_log=1;
}
if (opt_bin_log && !server_id)
{
......@@ -1720,6 +1723,7 @@ The server will not act as a slave.");
mysql_bin_log.set_index_file_name(opt_binlog_index_name);
open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
LOG_BIN);
using_update_log=1;
}
if (opt_slow_log)
......@@ -1730,10 +1734,10 @@ The server will not act as a slave.");
sql_print_error("Can't init databases");
exit(1);
}
ha_key_cache();
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
if (locked_in_memory && !geteuid())
{
ha_key_cache();
if (mlockall(MCL_CURRENT))
{
sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno);
......
......@@ -335,10 +335,6 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
VOID(hash_delete(&open_cache,(byte*) unused_tables));
#endif
}
if (!open_cache.records && ! locked_in_memory)
{
end_key_cache(); /* No tables in memory */
}
refresh_version++; // Force close of open tables
}
else
......@@ -703,8 +699,6 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->key_length=key_length;
table->version=0;
table->flush_version=0;
if (!key_cache_inited)
ha_key_cache();
table->in_use = thd;
check_unused();
pthread_mutex_unlock(&LOCK_open);
......@@ -857,8 +851,6 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->key_length=key_length;
table->version=refresh_version;
table->flush_version=flush_version;
if (!key_cache_inited)
ha_key_cache();
DBUG_PRINT("info", ("inserting table %p into the cache", table));
VOID(hash_insert(&open_cache,(byte*) table));
}
......
......@@ -3635,7 +3635,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
in the first 'hidden_null_pack_length' bytes of the row.
*/
null_pack_length-=hidden_null_pack_length;
keyinfo->key_parts= ((field_count-hidden_field_count)+
keyinfo->key_parts= ((field_count-param->hidden_field_count)+
test(null_pack_length));
if (allow_distinct_limit)
{
......
......@@ -699,7 +699,7 @@ create3:
/* empty */ {}
| opt_duplicate opt_as SELECT_SYM
{
Lex->lock_option= TL_READ_NO_INSERT;
Lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(Lex);
}
select_options select_item_list opt_select_from {}
......@@ -2072,7 +2072,7 @@ insert_values:
LEX *lex=Lex;
lex->sql_command = (lex->sql_command == SQLCOM_INSERT ?
SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT);
lex->lock_option= TL_READ_NO_INSERT;
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
}
select_options select_item_list select_from select_lock_type {}
......
......@@ -23,7 +23,7 @@ print "Connection to database $test_db\n";
$dbh = Mysql->Connect($host) || die "Can't connect: $Mysql::db_errstr\n";
$dbh->SelectDB($test_db) || die "Can't use database $test_db: $Mysql::db_errstr\n";
$dbh->Query("drop table export"); # Ignore this error
$dbh->Query("drop table if exists export"); # Ignore this error
print "Creating table\n";
......
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