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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
3a75900b
Commit
3a75900b
authored
Nov 11, 2013
by
unknown
Browse files
Options
Browse Files
Download
Plain Diff
merge 5.5->10.0-base
parents
8f0be1ad
dfed4478
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
245 additions
and
31 deletions
+245
-31
client/mysqltest.cc
client/mysqltest.cc
+4
-0
mysql-test/r/func_equal.result
mysql-test/r/func_equal.result
+44
-0
mysql-test/r/view.result
mysql-test/r/view.result
+31
-0
mysql-test/suite/mtr2/overlay.inc
mysql-test/suite/mtr2/overlay.inc
+2
-0
mysql-test/suite/mtr2/single.result
mysql-test/suite/mtr2/single.result
+3
-0
mysql-test/suite/mtr2/single.test
mysql-test/suite/mtr2/single.test
+4
-0
mysql-test/t/func_equal.test
mysql-test/t/func_equal.test
+51
-1
mysql-test/t/view.test
mysql-test/t/view.test
+28
-0
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+31
-5
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+1
-0
sql/item_subselect.cc
sql/item_subselect.cc
+19
-19
sql/opt_subselect.cc
sql/opt_subselect.cc
+13
-6
storage/myisam/mysql-test/mtr2/overlay.inc
storage/myisam/mysql-test/mtr2/overlay.inc
+2
-0
storage/myisam/mysql-test/mtr2/single.rdiff
storage/myisam/mysql-test/mtr2/single.rdiff
+12
-0
No files found.
client/mysqltest.cc
View file @
3a75900b
...
...
@@ -3041,6 +3041,10 @@ void open_file(const char *name)
5.try in basedir
*/
#ifdef __WIN__
fix_win_paths
(
curname
,
sizeof
(
curname
));
#endif
bool
in_overlay
=
opt_overlay_dir
&&
!
strncmp
(
curname
,
opt_overlay_dir
,
overlay_dir_len
);
bool
in_suiteir
=
opt_overlay_dir
&&
!
in_overlay
&&
...
...
mysql-test/r/func_equal.result
View file @
3a75900b
...
...
@@ -42,3 +42,47 @@ select * from t1 where a in ('4828532208463511553');
a
4828532208463511553
drop table t1;
#End of 4.1 tests
#
# MDEV-5103: server crashed on singular Item_equal
#
CREATE TABLE `t1` (
`tipo` enum('p','r') NOT NULL DEFAULT 'r',
`arquivo_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`arquivo_md5` char(32) NOT NULL,
`conteudo` longblob NOT NULL,
`usuario` varchar(15) NOT NULL,
`datahora_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`tipo_arquivo` varchar(255) NOT NULL,
`nome_arquivo` varchar(255) NOT NULL,
`tamanho_arquivo` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`tipo`,`arquivo_id`),
UNIQUE KEY `tipo` (`tipo`,`arquivo_md5`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO `t1` (`tipo`, `arquivo_id`, `arquivo_md5`, `conteudo`, `usuario`, `datahora_gmt`, `tipo_arquivo`, `nome_arquivo`, `tamanho_arquivo`) VALUES
('r', 1, 'ad18832202b199728921807033a8a515', '', 'rspadim', '2013-10-05 13:55:50', '001_cbr643', 'CBR6431677410201314132.ret', 21306);
CREATE TABLE `t2` (
`tipo` enum('p','r') NOT NULL DEFAULT 'p',
`arquivo_id` bigint(20) NOT NULL DEFAULT '0',
`usuario` varchar(25) NOT NULL,
`datahora` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`erros` longblob NOT NULL,
`importados` bigint(20) unsigned NOT NULL DEFAULT '0',
`n_importados` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`tipo`,`arquivo_id`,`datahora`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1;
INSERT INTO `t2` (`tipo`, `arquivo_id`, `usuario`, `datahora`, `erros`, `importados`, `n_importados`) VALUES
('r', 1, 'rspadim', '2013-10-05 14:25:30', '', 32, 0);
SELECT
arquivo_id,usuario,datahora_gmt,tipo_arquivo,nome_arquivo,tamanho_arquivo
FROM t1 AS a
WHERE datahora_gmt>='0000-00-00 00:00:00' AND
datahora_gmt<='2013-10-07 02:59:59' AND tipo='r' AND
(tipo_arquivo,arquivo_id) NOT IN
(SELECT tipo_arquivo,arquivo_id
FROM t2
WHERE (tipo_arquivo,arquivo_id)=(a.tipo_arquivo,a.arquivo_id))
ORDER BY arquivo_id DESC;
arquivo_id usuario datahora_gmt tipo_arquivo nome_arquivo tamanho_arquivo
drop table t2, t1;
#End of 5.3 tests
mysql-test/r/view.result
View file @
3a75900b
...
...
@@ -4921,6 +4921,37 @@ q 1 q
q 1 q
drop view v1;
drop table t1,t2;
#
# MDEV-5153: Server crashes in Item_ref::fix_fields on 2nd execution
# of PS with LEFT JOIN and MERGE view or SELECT SQ
#
CREATE TABLE t1 (i1 INT, c1 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
CREATE TABLE t2 (c2 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('foobar'),('qux');
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1 ) IN ( SELECT c2 FROM t2 ) AND i1 <= 2 ;
PREPARE stmt FROM 'SELECT * FROM t1 LEFT JOIN v1 ON (v1.i1 = t1.i1)';
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
drop view v1;
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1, c1 ) IN ( SELECT c2, c2 FROM t2 ) AND i1 <= 2 ;
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
deallocate prepare stmt;
drop view v1;
drop table t1,t2;
# -----------------------------------------------------------------
# -- End of 5.3 tests.
# -----------------------------------------------------------------
...
...
mysql-test/suite/mtr2/overlay.inc
0 → 100644
View file @
3a75900b
select
2
;
mysql-test/suite/mtr2/single.result
View file @
3a75900b
select 1;
1
1
select 2;
2
2
mysql-test/suite/mtr2/single.test
View file @
3a75900b
...
...
@@ -5,4 +5,8 @@
# three times - once for the parent suite, and once for each overlay.
# even if the test files are not overlayed.
#
# overlay.inc is overridden in mtr2-myisam, and there is an rdiff file.
#
select
1
;
source
overlay
.
inc
;
mysql-test/t/func_equal.test
View file @
3a75900b
...
...
@@ -43,4 +43,54 @@ select * from t1 where a = '4828532208463511553';
select
*
from
t1
where
a
in
(
'4828532208463511553'
);
drop
table
t1
;
# End of 4.1 tests
--
echo
#End of 4.1 tests
--
echo
#
--
echo
# MDEV-5103: server crashed on singular Item_equal
--
echo
#
CREATE
TABLE
`t1`
(
`tipo`
enum
(
'p'
,
'r'
)
NOT
NULL
DEFAULT
'r'
,
`arquivo_id`
bigint
(
20
)
unsigned
NOT
NULL
DEFAULT
'0'
,
`arquivo_md5`
char
(
32
)
NOT
NULL
,
`conteudo`
longblob
NOT
NULL
,
`usuario`
varchar
(
15
)
NOT
NULL
,
`datahora_gmt`
datetime
NOT
NULL
DEFAULT
'0000-00-00 00:00:00'
,
`tipo_arquivo`
varchar
(
255
)
NOT
NULL
,
`nome_arquivo`
varchar
(
255
)
NOT
NULL
,
`tamanho_arquivo`
bigint
(
20
)
unsigned
NOT
NULL
DEFAULT
'0'
,
PRIMARY
KEY
(
`tipo`
,
`arquivo_id`
),
UNIQUE
KEY
`tipo`
(
`tipo`
,
`arquivo_md5`
)
)
ENGINE
=
Aria
DEFAULT
CHARSET
=
latin1
PAGE_CHECKSUM
=
1
;
INSERT
INTO
`t1`
(
`tipo`
,
`arquivo_id`
,
`arquivo_md5`
,
`conteudo`
,
`usuario`
,
`datahora_gmt`
,
`tipo_arquivo`
,
`nome_arquivo`
,
`tamanho_arquivo`
)
VALUES
(
'r'
,
1
,
'ad18832202b199728921807033a8a515'
,
''
,
'rspadim'
,
'2013-10-05 13:55:50'
,
'001_cbr643'
,
'CBR6431677410201314132.ret'
,
21306
);
CREATE
TABLE
`t2`
(
`tipo`
enum
(
'p'
,
'r'
)
NOT
NULL
DEFAULT
'p'
,
`arquivo_id`
bigint
(
20
)
NOT
NULL
DEFAULT
'0'
,
`usuario`
varchar
(
25
)
NOT
NULL
,
`datahora`
datetime
NOT
NULL
DEFAULT
'0000-00-00 00:00:00'
,
`erros`
longblob
NOT
NULL
,
`importados`
bigint
(
20
)
unsigned
NOT
NULL
DEFAULT
'0'
,
`n_importados`
bigint
(
20
)
unsigned
NOT
NULL
DEFAULT
'0'
,
PRIMARY
KEY
(
`tipo`
,
`arquivo_id`
,
`datahora`
)
)
ENGINE
=
Aria
DEFAULT
CHARSET
=
latin1
PAGE_CHECKSUM
=
1
;
INSERT
INTO
`t2`
(
`tipo`
,
`arquivo_id`
,
`usuario`
,
`datahora`
,
`erros`
,
`importados`
,
`n_importados`
)
VALUES
(
'r'
,
1
,
'rspadim'
,
'2013-10-05 14:25:30'
,
''
,
32
,
0
);
SELECT
arquivo_id
,
usuario
,
datahora_gmt
,
tipo_arquivo
,
nome_arquivo
,
tamanho_arquivo
FROM
t1
AS
a
WHERE
datahora_gmt
>=
'0000-00-00 00:00:00'
AND
datahora_gmt
<=
'2013-10-07 02:59:59'
AND
tipo
=
'r'
AND
(
tipo_arquivo
,
arquivo_id
)
NOT
IN
(
SELECT
tipo_arquivo
,
arquivo_id
FROM
t2
WHERE
(
tipo_arquivo
,
arquivo_id
)
=
(
a
.
tipo_arquivo
,
a
.
arquivo_id
))
ORDER
BY
arquivo_id
DESC
;
drop
table
t2
,
t1
;
--
echo
#End of 5.3 tests
mysql-test/t/view.test
View file @
3a75900b
...
...
@@ -4845,6 +4845,34 @@ SELECT * FROM t2 LEFT JOIN v1 ON ( c=b AND a IN ( 1,6 ) );
drop
view
v1
;
drop
table
t1
,
t2
;
--
echo
#
--
echo
# MDEV-5153: Server crashes in Item_ref::fix_fields on 2nd execution
--
echo
# of PS with LEFT JOIN and MERGE view or SELECT SQ
--
echo
#
CREATE
TABLE
t1
(
i1
INT
,
c1
VARCHAR
(
6
))
ENGINE
=
MyISAM
;
INSERT
INTO
t1
VALUES
(
1
,
'foo'
),(
2
,
'bar'
);
CREATE
TABLE
t2
(
c2
VARCHAR
(
6
))
ENGINE
=
MyISAM
;
INSERT
INTO
t2
VALUES
(
'foobar'
),(
'qux'
);
CREATE
ALGORITHM
=
MERGE
VIEW
v1
AS
SELECT
*
FROM
t1
WHERE
(
c1
)
IN
(
SELECT
c2
FROM
t2
)
AND
i1
<=
2
;
PREPARE
stmt
FROM
'SELECT * FROM t1 LEFT JOIN v1 ON (v1.i1 = t1.i1)'
;
EXECUTE
stmt
;
EXECUTE
stmt
;
drop
view
v1
;
CREATE
ALGORITHM
=
MERGE
VIEW
v1
AS
SELECT
*
FROM
t1
WHERE
(
c1
,
c1
)
IN
(
SELECT
c2
,
c2
FROM
t2
)
AND
i1
<=
2
;
EXECUTE
stmt
;
EXECUTE
stmt
;
deallocate
prepare
stmt
;
drop
view
v1
;
drop
table
t1
,
t2
;
--
echo
# -----------------------------------------------------------------
--
echo
# -- End of 5.3 tests.
--
echo
# -----------------------------------------------------------------
...
...
sql/item_cmpfunc.cc
View file @
3a75900b
...
...
@@ -1438,9 +1438,11 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg)
bool
Item_in_optimizer
::
fix_left
(
THD
*
thd
)
{
DBUG_ENTER
(
"Item_in_optimizer::fix_left"
);
if
((
!
args
[
0
]
->
fixed
&&
args
[
0
]
->
fix_fields
(
thd
,
args
))
||
(
!
cache
&&
!
(
cache
=
Item_cache
::
get_cache
(
args
[
0
]))))
return
1
;
DBUG_RETURN
(
1
);
DBUG_PRINT
(
"info"
,
(
"actual fix fields"
));
cache
->
setup
(
args
[
0
]);
if
(
cache
->
cols
()
==
1
)
...
...
@@ -1466,11 +1468,15 @@ bool Item_in_optimizer::fix_left(THD *thd)
{
my_error
(
ER_NOT_SUPPORTED_YET
,
MYF
(
0
),
"SUBQUERY in ROW in left expression of IN/ALL/ANY"
);
return
1
;
DBUG_RETURN
(
1
)
;
}
Item
*
element
=
args
[
0
]
->
element_index
(
i
);
if
(
element
->
used_tables
()
||
!
element
->
const_item
())
((
Item_cache
*
)
cache
->
element_index
(
i
))
->
set_used_tables
(
OUTER_REF_TABLE_BIT
);
{
((
Item_cache
*
)
cache
->
element_index
(
i
))
->
set_used_tables
(
OUTER_REF_TABLE_BIT
);
cache
->
set_used_tables
(
OUTER_REF_TABLE_BIT
);
}
else
((
Item_cache
*
)
cache
->
element_index
(
i
))
->
set_used_tables
(
0
);
}
...
...
@@ -1491,7 +1497,7 @@ bool Item_in_optimizer::fix_left(THD *thd)
with_sum_func
=
with_sum_func
||
args
[
1
]
->
with_sum_func
;
const_item_cache
=
const_item_cache
&&
args
[
1
]
->
const_item
();
}
return
0
;
DBUG_RETURN
(
0
)
;
}
...
...
@@ -5794,6 +5800,12 @@ void Item_equal::add_const(Item *c, Item *f)
func
->
quick_fix_field
();
cond_false
=
!
func
->
val_int
();
}
/*
TODO: also support the case where Item_equal becomes singular with
this->is_cond_true()=1. When I attempted to mark the item as constant,
the optimizer attempted to remove it, however it is still referenced from
COND_EQUAL and I got a crash.
*/
if
(
cond_false
)
const_item_cache
=
1
;
}
...
...
@@ -5998,6 +6010,7 @@ void Item_equal::merge_into_list(List<Item_equal> *list,
void
Item_equal
::
sort
(
Item_field_cmpfunc
compare
,
void
*
arg
)
{
if
(
equal_items
.
elements
>
1
)
bubble_sort
<
Item
>
(
&
equal_items
,
compare
,
arg
);
}
...
...
@@ -6126,6 +6139,12 @@ bool Item_equal::fix_fields(THD *thd, Item **ref)
void
Item_equal
::
update_used_tables
()
{
not_null_tables_cache
=
used_tables_cache
=
0
;
/*
TODO: also support the case where Item_equal becomes singular with
this->is_cond_true()=1. When I attempted to mark the item as constant,
the optimizer attempted to remove it, however it is still referenced from
COND_EQUAL and I got a crash.
*/
if
((
const_item_cache
=
cond_false
))
return
;
Item_equal_fields_iterator
it
(
*
this
);
...
...
@@ -6175,6 +6194,8 @@ longlong Item_equal::val_int()
{
if
(
cond_false
)
return
0
;
if
(
is_cond_true
())
return
1
;
Item
*
item
=
get_const
();
Item_equal_fields_iterator
it
(
*
this
);
if
(
!
item
)
...
...
@@ -6199,6 +6220,11 @@ longlong Item_equal::val_int()
void
Item_equal
::
fix_length_and_dec
()
{
Item
*
item
=
get_first
(
NO_PARTICULAR_TAB
,
NULL
);
if
(
!
item
)
{
DBUG_ASSERT
(
is_cond_true
());
// it should be the only constant
item
=
equal_items
.
head
();
}
eval_item
=
cmp_item
::
get_comparator
(
item
->
cmp_type
(),
item
,
item
->
collation
.
collation
);
}
...
...
sql/item_cmpfunc.h
View file @
3a75900b
...
...
@@ -1826,6 +1826,7 @@ class Item_equal: public Item_bool_func
Item_equal
(
Item_equal
*
item_equal
);
/* Currently the const item is always the first in the list of equal items */
inline
Item
*
get_const
()
{
return
with_const
?
equal_items
.
head
()
:
NULL
;
}
inline
bool
is_cond_true
()
{
return
equal_items
.
elements
==
1
;
}
void
add_const
(
Item
*
c
,
Item
*
f
=
NULL
);
/** Add a non-constant item to the multiple equality */
void
add
(
Item
*
f
)
{
equal_items
.
push_back
(
f
);
}
...
...
sql/item_subselect.cc
View file @
3a75900b
...
...
@@ -2277,7 +2277,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
DBUG_RETURN
(
true
);
Item
*
item_eq
=
new
Item_func_eq
(
new
Item_ref
(
&
select_lex
->
context
,
Item_
direct_
ref
(
&
select_lex
->
context
,
(
*
optimizer
->
get_cache
())
->
addr
(
i
),
(
char
*
)
"<no matter>"
,
...
...
@@ -3000,7 +3000,7 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg)
bool
Item_in_subselect
::
select_in_like_transformer
(
JOIN
*
join
)
{
Query_arena
*
arena
,
backup
;
Query_arena
*
arena
=
0
,
backup
;
SELECT_LEX
*
current
=
thd
->
lex
->
current_select
;
const
char
*
save_where
=
thd
->
where
;
bool
trans_res
=
true
;
...
...
@@ -3022,9 +3022,6 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
}
}
if
(
changed
)
DBUG_RETURN
(
false
);
thd
->
where
=
"IN/ALL/ANY subquery"
;
/*
...
...
@@ -3035,25 +3032,29 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
note: we won't need Item_in_optimizer when handling degenerate cases
like "... IN (SELECT 1)"
*/
arena
=
thd
->
activate_stmt_arena_if_needed
(
&
backup
);
if
(
!
optimizer
)
{
arena
=
thd
->
activate_stmt_arena_if_needed
(
&
backup
);
result
=
(
!
(
optimizer
=
new
Item_in_optimizer
(
left_expr
,
this
)));
if
(
arena
)
thd
->
restore_active_arena
(
arena
,
&
backup
);
if
(
result
)
goto
err
;
goto
out
;
}
thd
->
lex
->
current_select
=
current
->
return_after_parsing
();
result
=
(
!
left_expr
->
fixed
&&
left_expr
->
fix_fields
(
thd
,
optimizer
->
arguments
()));
result
=
optimizer
->
fix_left
(
thd
);
/* fix_fields can change reference to left_expr, we need reassign it */
left_expr
=
optimizer
->
arguments
()[
0
];
thd
->
lex
->
current_select
=
current
;
if
(
changed
)
{
trans_res
=
false
;
goto
out
;
}
if
(
result
)
goto
err
;
goto
out
;
/*
Both transformers call fix_fields() only for Items created inside them,
...
...
@@ -3062,7 +3063,6 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
of Item, we have to call fix_fields() for it only with original arena to
avoid memory leack)
*/
arena
=
thd
->
activate_stmt_arena_if_needed
(
&
backup
);
if
(
left_expr
->
cols
()
==
1
)
trans_res
=
single_value_transformer
(
join
);
else
...
...
@@ -3077,9 +3077,9 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
}
trans_res
=
row_value_transformer
(
join
);
}
out:
if
(
arena
)
thd
->
restore_active_arena
(
arena
,
&
backup
);
err:
thd
->
where
=
save_where
;
DBUG_RETURN
(
trans_res
);
}
...
...
sql/opt_subselect.cc
View file @
3a75900b
...
...
@@ -1272,10 +1272,10 @@ void get_delayed_table_estimates(TABLE *table,
@brief Replaces an expression destructively inside the expression tree of
the WHERE clase.
@note
Because of current requirements for semijoin flattening, we do not
need to recurse here, hence this function will only examine the top-level
AND conditions. (see JOIN::prepare, comment starting with "Check if the
subquery predicate can be executed via materialization"
.
@note
We substitute AND/OR structure because it was copied by
copy_andor_structure and some changes could be done in the copy but
should be left permanent, also there could be several layers of AND over
AND and OR over OR because ::fix_field() possibly is not called
.
@param join The top-level query.
@param old_cond The expression to be replaced.
...
...
@@ -1311,6 +1311,13 @@ static bool replace_where_subcondition(JOIN *join, Item **expr,
new_cond
->
fix_fields
(
join
->
thd
,
li
.
ref
());
return
FALSE
;
}
else
if
(
item
->
type
()
==
Item
::
COND_ITEM
)
{
DBUG_ASSERT
(
!
(
*
expr
)
->
fixed
);
replace_where_subcondition
(
join
,
li
.
ref
(),
old_cond
,
new_cond
,
do_fix_fields
);
}
}
}
/*
...
...
storage/myisam/mysql-test/mtr2/overlay.inc
0 → 100644
View file @
3a75900b
select
3
;
storage/myisam/mysql-test/mtr2/single.rdiff
0 → 100644
View file @
3a75900b
--- suite/mtr2/single.result 2013-11-10 03:58:37.000000000 +0400
+++ suite/mtr2/single.reject 2013-11-10 03:59:08.000000000 +0400
@@ -1,6 +1,6 @@
select 1;
1
1
-select 2;
-2
-2
+select 3;
+3
+3
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