Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
7e5d7b84
Commit
7e5d7b84
authored
19 years ago
by
unknown
Browse files
Options
Browse Files
Download
Plain Diff
Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-5.0
parents
0f8b518b
47dc78e6
No related merge requests found
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
182 additions
and
171 deletions
+182
-171
mysql-test/r/view.result
mysql-test/r/view.result
+0
-101
mysql-test/r/view_query_cache.result
mysql-test/r/view_query_cache.result
+101
-0
mysql-test/t/view.test
mysql-test/t/view.test
+0
-57
mysql-test/t/view_query_cache.test
mysql-test/t/view_query_cache.test
+58
-0
sql/item_func.cc
sql/item_func.cc
+1
-1
sql/sql_base.cc
sql/sql_base.cc
+12
-7
sql/sql_yacc.yy
sql/sql_yacc.yy
+4
-1
sql/table.cc
sql/table.cc
+5
-4
sql/table.h
sql/table.h
+1
-0
No files found.
mysql-test/r/view.result
View file @
7e5d7b84
...
@@ -363,107 +363,6 @@ v4 CREATE ALGORITHM=TEMPTABLE VIEW `mysqltest`.`v4` AS select (`mysqltest`.`t2`.
...
@@ -363,107 +363,6 @@ v4 CREATE ALGORITHM=TEMPTABLE VIEW `mysqltest`.`v4` AS select (`mysqltest`.`t2`.
revoke all privileges on mysqltest.* from mysqltest_1@localhost;
revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1';
delete from mysql.user where user='mysqltest_1';
drop database mysqltest;
drop database mysqltest;
set GLOBAL query_cache_size=1355776;
flush status;
create table t1 (a int, b int);
create view v1 (c,d) as select sql_no_cache a,b from t1;
create view v2 (c,d) as select a+rand(),b from t1;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 0
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from v1;
c d
select * from v2;
c d
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 0
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from v1;
c d
select * from v2;
c d
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 0
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
drop view v1,v2;
set query_cache_type=demand;
flush status;
create view v1 (c,d) as select sql_cache a,b from t1;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 0
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from v1;
c d
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from t1;
a b
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from v1;
c d
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 1
select * from t1;
a b
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 1
drop view v1;
set query_cache_type=default;
drop table t1;
set GLOBAL query_cache_size=default;
create table t1 (a int);
create table t1 (a int);
insert into t1 values (1), (2), (3), (1), (2), (3);
insert into t1 values (1), (2), (3), (1), (2), (3);
create view v1 as select distinct a from t1;
create view v1 as select distinct a from t1;
...
...
This diff is collapsed.
Click to expand it.
mysql-test/r/view_query_cache.result
0 → 100644
View file @
7e5d7b84
set GLOBAL query_cache_size=1355776;
flush status;
create table t1 (a int, b int);
create view v1 (c,d) as select sql_no_cache a,b from t1;
create view v2 (c,d) as select a+rand(),b from t1;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 0
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from v1;
c d
select * from v2;
c d
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 0
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from v1;
c d
select * from v2;
c d
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 0
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
drop view v1,v2;
set query_cache_type=demand;
flush status;
create view v1 (c,d) as select sql_cache a,b from t1;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 0
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from v1;
c d
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from t1;
a b
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
select * from v1;
c d
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 1
select * from t1;
a b
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 1
drop view v1;
set query_cache_type=default;
drop table t1;
set GLOBAL query_cache_size=default;
This diff is collapsed.
Click to expand it.
mysql-test/t/view.test
View file @
7e5d7b84
...
@@ -328,63 +328,6 @@ revoke all privileges on mysqltest.* from mysqltest_1@localhost;
...
@@ -328,63 +328,6 @@ revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete
from
mysql
.
user
where
user
=
'mysqltest_1'
;
delete
from
mysql
.
user
where
user
=
'mysqltest_1'
;
drop
database
mysqltest
;
drop
database
mysqltest
;
#
# QUERY CACHE options for VIEWs
#
set
GLOBAL
query_cache_size
=
1355776
;
flush
status
;
create
table
t1
(
a
int
,
b
int
);
# queries with following views should not be in query cache
create
view
v1
(
c
,
d
)
as
select
sql_no_cache
a
,
b
from
t1
;
create
view
v2
(
c
,
d
)
as
select
a
+
rand
(),
b
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
v1
;
select
*
from
v2
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
v1
;
select
*
from
v2
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
drop
view
v1
,
v2
;
# SQL_CACHE option
set
query_cache_type
=
demand
;
flush
status
;
# query with view will be cached, but direct acess to table will not
create
view
v1
(
c
,
d
)
as
select
sql_cache
a
,
b
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
v1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
v1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
drop
view
v1
;
set
query_cache_type
=
default
;
drop
table
t1
;
set
GLOBAL
query_cache_size
=
default
;
#
#
# DISTINCT option for VIEW
# DISTINCT option for VIEW
#
#
...
...
This diff is collapsed.
Click to expand it.
mysql-test/t/view_query_cache.test
0 → 100644
View file @
7e5d7b84
--
source
include
/
have_query_cache
.
inc
#
# QUERY CACHE options for VIEWs
#
set
GLOBAL
query_cache_size
=
1355776
;
flush
status
;
create
table
t1
(
a
int
,
b
int
);
# queries with following views should not be in query cache
create
view
v1
(
c
,
d
)
as
select
sql_no_cache
a
,
b
from
t1
;
create
view
v2
(
c
,
d
)
as
select
a
+
rand
(),
b
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
v1
;
select
*
from
v2
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
v1
;
select
*
from
v2
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
drop
view
v1
,
v2
;
# SQL_CACHE option
set
query_cache_type
=
demand
;
flush
status
;
# query with view will be cached, but direct acess to table will not
create
view
v1
(
c
,
d
)
as
select
sql_cache
a
,
b
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
v1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
v1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
select
*
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_inserts"
;
show
status
like
"Qcache_hits"
;
drop
view
v1
;
set
query_cache_type
=
default
;
drop
table
t1
;
set
GLOBAL
query_cache_size
=
default
;
This diff is collapsed.
Click to expand it.
sql/item_func.cc
View file @
7e5d7b84
...
@@ -194,8 +194,8 @@ bool Item_func::agg_arg_charsets(DTCollation &coll,
...
@@ -194,8 +194,8 @@ bool Item_func::agg_arg_charsets(DTCollation &coll,
}
}
if
((
*
arg
)
->
type
()
==
FIELD_ITEM
)
if
((
*
arg
)
->
type
()
==
FIELD_ITEM
)
((
Item_field
*
)(
*
arg
))
->
no_const_subst
=
1
;
((
Item_field
*
)(
*
arg
))
->
no_const_subst
=
1
;
conv
->
fix_fields
(
thd
,
0
,
&
conv
);
*
arg
=
conv
;
*
arg
=
conv
;
conv
->
fix_fields
(
thd
,
0
,
arg
);
}
}
if
(
arena
)
if
(
arena
)
thd
->
restore_backup_item_arena
(
arena
,
&
backup
);
thd
->
restore_backup_item_arena
(
arena
,
&
backup
);
...
...
This diff is collapsed.
Click to expand it.
sql/sql_base.cc
View file @
7e5d7b84
...
@@ -2262,7 +2262,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
...
@@ -2262,7 +2262,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
field makes some prepared query ambiguous and so erroneous, but we
field makes some prepared query ambiguous and so erroneous, but we
accept this trade off.
accept this trade off.
*/
*/
if
(
item
->
cached_table
->
table
)
if
(
item
->
cached_table
->
table
&&
!
item
->
cached_table
->
view
)
{
{
found
=
find_field_in_real_table
(
thd
,
item
->
cached_table
->
table
,
found
=
find_field_in_real_table
(
thd
,
item
->
cached_table
->
table
,
name
,
length
,
name
,
length
,
...
@@ -3047,15 +3047,19 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
...
@@ -3047,15 +3047,19 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
&
not_used_field_index
,
TRUE
))
&
not_used_field_index
,
TRUE
))
{
{
Item
*
item
=
iterator
->
item
(
thd
);
Item
*
item
=
iterator
->
item
(
thd
);
if
(
view
&&
!
thd
->
lex
->
current_select
->
no_wrap_view_item
)
{
/*
as far as we have view, then item point to view_iter, so we
can use it directly for this view specific operation
*/
item
=
new
Item_ref
(
view_iter
.
item_ptr
(),
tables
->
view_name
.
str
,
field_name
);
}
if
(
!
found
++
)
if
(
!
found
++
)
(
void
)
it
->
replace
(
item
);
// Replace '*'
(
void
)
it
->
replace
(
item
);
// Replace '*'
else
else
it
->
after
(
item
);
it
->
after
(
item
);
if
(
view
&&
!
thd
->
lex
->
current_select
->
no_wrap_view_item
)
{
item
=
new
Item_ref
(
it
->
ref
(),
tables
->
view_name
.
str
,
field_name
);
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if
(
any_privileges
)
if
(
any_privileges
)
{
{
...
@@ -3328,7 +3332,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
...
@@ -3328,7 +3332,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
thd
->
restore_backup_item_arena
(
arena
,
&
backup
);
thd
->
restore_backup_item_arena
(
arena
,
&
backup
);
if
(
embedded
->
on_expr
&&
!
embedded
->
on_expr
->
fixed
)
if
(
embedded
->
on_expr
&&
!
embedded
->
on_expr
->
fixed
)
{
{
if
(
embedded
->
on_expr
->
fix_fields
(
thd
,
tables
,
&
table
->
on_expr
))
if
(
embedded
->
on_expr
->
fix_fields
(
thd
,
tables
,
&
embedded
->
on_expr
))
goto
err_no_arena
;
goto
err_no_arena
;
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
sql/sql_yacc.yy
View file @
7e5d7b84
...
@@ -5577,6 +5577,7 @@ insert:
...
@@ -5577,6 +5577,7 @@ insert:
LEX *lex= Lex;
LEX *lex= Lex;
lex->sql_command= SQLCOM_INSERT;
lex->sql_command= SQLCOM_INSERT;
lex->duplicates= DUP_ERROR;
lex->duplicates= DUP_ERROR;
mysql_init_select(lex);
/* for subselects */
/* for subselects */
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
...
@@ -5596,6 +5597,7 @@ replace:
...
@@ -5596,6 +5597,7 @@ replace:
LEX *lex=Lex;
LEX *lex=Lex;
lex->sql_command = SQLCOM_REPLACE;
lex->sql_command = SQLCOM_REPLACE;
lex->duplicates= DUP_REPLACE;
lex->duplicates= DUP_REPLACE;
mysql_init_select(lex);
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
}
}
replace_lock_option insert2
replace_lock_option insert2
...
@@ -5796,6 +5798,7 @@ delete:
...
@@ -5796,6 +5798,7 @@ delete:
{
{
LEX *lex= Lex;
LEX *lex= Lex;
lex->sql_command= SQLCOM_DELETE;
lex->sql_command= SQLCOM_DELETE;
mysql_init_select(lex);
lex->lock_option= lex->thd->update_lock_default;
lex->lock_option= lex->thd->update_lock_default;
lex->ignore= 0;
lex->ignore= 0;
lex->select_lex.init_order();
lex->select_lex.init_order();
...
@@ -7124,6 +7127,7 @@ set:
...
@@ -7124,6 +7127,7 @@ set:
{
{
LEX *lex=Lex;
LEX *lex=Lex;
lex->sql_command= SQLCOM_SET_OPTION;
lex->sql_command= SQLCOM_SET_OPTION;
mysql_init_select(lex);
lex->option_type=OPT_SESSION;
lex->option_type=OPT_SESSION;
lex->var_list.empty();
lex->var_list.empty();
lex->one_shot_set= 0;
lex->one_shot_set= 0;
...
@@ -7190,7 +7194,6 @@ option_value:
...
@@ -7190,7 +7194,6 @@ option_value:
}
}
else
else
lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4)));
lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4)));
}
}
| internal_variable_name equal set_expr_or_default
| internal_variable_name equal set_expr_or_default
{
{
...
...
This diff is collapsed.
Click to expand it.
sql/table.cc
View file @
7e5d7b84
...
@@ -1702,6 +1702,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
...
@@ -1702,6 +1702,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
if
(
field_translation
)
if
(
field_translation
)
{
{
DBUG_PRINT
(
"info"
,
(
"there are already translation table"
));
/* prevent look up in SELECTs tree */
/* prevent look up in SELECTs tree */
thd
->
lex
->
current_select
=
&
thd
->
lex
->
select_lex
;
thd
->
lex
->
current_select
=
&
thd
->
lex
->
select_lex
;
thd
->
lex
->
select_lex
.
no_wrap_view_item
=
1
;
thd
->
lex
->
select_lex
.
no_wrap_view_item
=
1
;
...
@@ -1727,7 +1728,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
...
@@ -1727,7 +1728,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
if
(
where
&&
!
where
->
fixed
&&
where
->
fix_fields
(
thd
,
ancestor
,
&
where
))
if
(
where
&&
!
where
->
fixed
&&
where
->
fix_fields
(
thd
,
ancestor
,
&
where
))
goto
err
;
goto
err
;
if
(
check_option
&&
!
check_option
->
fixed
&&
if
(
check_option
&&
!
check_option
->
fixed
&&
check_option
->
fix_fields
(
thd
,
ancestor
,
&
where
))
check_option
->
fix_fields
(
thd
,
ancestor
,
&
check_option
))
goto
err
;
goto
err
;
restore_want_privilege
();
restore_want_privilege
();
...
@@ -1767,11 +1768,11 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
...
@@ -1767,11 +1768,11 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
{
{
/* save original name of view column */
/* save original name of view column */
char
*
name
=
item
->
name
;
char
*
name
=
item
->
name
;
if
(
!
item
->
fixed
&&
item
->
fix_fields
(
thd
,
ancestor
,
&
item
))
transl
[
i
].
item
=
item
;
if
(
!
item
->
fixed
&&
item
->
fix_fields
(
thd
,
ancestor
,
&
transl
[
i
].
item
))
goto
err
;
goto
err
;
/* set new item get in fix fields and original column name */
/* set new item get in fix fields and original column name */
transl
[
i
].
name
=
name
;
transl
[
i
++
].
name
=
name
;
transl
[
i
++
].
item
=
item
;
}
}
field_translation
=
transl
;
field_translation
=
transl
;
/* TODO: sort this list? Use hash for big number of fields */
/* TODO: sort this list? Use hash for big number of fields */
...
...
This diff is collapsed.
Click to expand it.
sql/table.h
View file @
7e5d7b84
...
@@ -428,6 +428,7 @@ public:
...
@@ -428,6 +428,7 @@ public:
bool
end_of_fields
()
{
return
ptr
==
array_end
;
}
bool
end_of_fields
()
{
return
ptr
==
array_end
;
}
const
char
*
name
();
const
char
*
name
();
Item
*
item
(
THD
*
thd
)
{
return
ptr
->
item
;
}
Item
*
item
(
THD
*
thd
)
{
return
ptr
->
item
;
}
Item
**
item_ptr
()
{
return
&
ptr
->
item
;
}
Field
*
field
()
{
return
0
;
}
Field
*
field
()
{
return
0
;
}
};
};
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment