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
9791d534
Commit
9791d534
authored
Jun 27, 2006
by
tomas@poseidon.ndb.mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
partition functions to pass create_info, not only max_rows
parent
08bec7b9
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
45 additions
and
37 deletions
+45
-37
sql/ha_ndbcluster.cc
sql/ha_ndbcluster.cc
+18
-10
sql/ha_ndbcluster.h
sql/ha_ndbcluster.h
+1
-1
sql/handler.h
sql/handler.h
+1
-1
sql/partition_info.cc
sql/partition_info.cc
+14
-13
sql/partition_info.h
sql/partition_info.h
+4
-4
sql/sql_partition.cc
sql/sql_partition.cc
+1
-2
sql/sql_partition.h
sql/sql_partition.h
+1
-1
sql/sql_table.cc
sql/sql_table.cc
+5
-5
No files found.
sql/ha_ndbcluster.cc
View file @
9791d534
...
@@ -9590,12 +9590,8 @@ ndbcluster_show_status(THD* thd, stat_print_fn *stat_print,
...
@@ -9590,12 +9590,8 @@ ndbcluster_show_status(THD* thd, stat_print_fn *stat_print,
/*
/*
Create a table in NDB Cluster
Create a table in NDB Cluster
*/
*/
static
uint
get_no_fragments
(
TABLE_SHARE
*
table_share
)
static
uint
get_no_fragments
(
ulonglong
max_rows
)
{
{
ha_rows
max_rows
=
table_share
->
max_rows
;
ha_rows
min_rows
=
table_share
->
min_rows
;
if
(
max_rows
<
min_rows
)
max_rows
=
min_rows
;
#if MYSQL_VERSION_ID >= 50000
#if MYSQL_VERSION_ID >= 50000
uint
acc_row_size
=
25
+
/*safety margin*/
2
;
uint
acc_row_size
=
25
+
/*safety margin*/
2
;
#else
#else
...
@@ -9632,10 +9628,22 @@ static bool adjusted_frag_count(uint no_fragments, uint no_nodes,
...
@@ -9632,10 +9628,22 @@ static bool adjusted_frag_count(uint no_fragments, uint no_nodes,
return
(
reported_frags
<
no_fragments
);
return
(
reported_frags
<
no_fragments
);
}
}
int
ha_ndbcluster
::
get_default_no_partitions
(
TABLE_SHARE
*
table_share
)
int
ha_ndbcluster
::
get_default_no_partitions
(
HA_CREATE_INFO
*
info
)
{
{
ha_rows
max_rows
,
min_rows
;
if
(
info
)
{
max_rows
=
info
->
max_rows
;
min_rows
=
info
->
min_rows
;
}
else
{
max_rows
=
table_share
->
max_rows
;
min_rows
=
table_share
->
min_rows
;
}
uint
reported_frags
;
uint
reported_frags
;
uint
no_fragments
=
get_no_fragments
(
table_share
);
uint
no_fragments
=
get_no_fragments
(
max_rows
>=
min_rows
?
max_rows
:
min_rows
);
uint
no_nodes
=
g_ndb_cluster_connection
->
no_db_nodes
();
uint
no_nodes
=
g_ndb_cluster_connection
->
no_db_nodes
();
if
(
adjusted_frag_count
(
no_fragments
,
no_nodes
,
reported_frags
))
if
(
adjusted_frag_count
(
no_fragments
,
no_nodes
,
reported_frags
))
{
{
...
@@ -9884,14 +9892,14 @@ uint ha_ndbcluster::set_up_partition_info(partition_info *part_info,
...
@@ -9884,14 +9892,14 @@ uint ha_ndbcluster::set_up_partition_info(partition_info *part_info,
tab
->
setDefaultNoPartitionsFlag
(
part_info
->
use_default_no_partitions
);
tab
->
setDefaultNoPartitionsFlag
(
part_info
->
use_default_no_partitions
);
tab
->
setLinearFlag
(
part_info
->
linear_hash_ind
);
tab
->
setLinearFlag
(
part_info
->
linear_hash_ind
);
{
{
ha_rows
max_rows
=
form
->
s
->
max_rows
;
ha_rows
max_rows
=
table_share
->
max_rows
;
ha_rows
min_rows
=
form
->
s
->
min_rows
;
ha_rows
min_rows
=
table_share
->
min_rows
;
if
(
max_rows
<
min_rows
)
if
(
max_rows
<
min_rows
)
max_rows
=
min_rows
;
max_rows
=
min_rows
;
if
(
max_rows
!=
(
ha_rows
)
0
)
/* default setting, don't set fragmentation */
if
(
max_rows
!=
(
ha_rows
)
0
)
/* default setting, don't set fragmentation */
{
{
tab
->
setMaxRows
(
max_rows
);
tab
->
setMaxRows
(
max_rows
);
tab
->
setM
ax
Rows
(
min_rows
);
tab
->
setM
in
Rows
(
min_rows
);
}
}
}
}
tab
->
setTablespaceNames
(
ts_names
,
fd_index
*
sizeof
(
char
*
));
tab
->
setTablespaceNames
(
ts_names
,
fd_index
*
sizeof
(
char
*
));
...
...
sql/ha_ndbcluster.h
View file @
9791d534
...
@@ -651,7 +651,7 @@ class ha_ndbcluster: public handler
...
@@ -651,7 +651,7 @@ class ha_ndbcluster: public handler
int
create
(
const
char
*
name
,
TABLE
*
form
,
HA_CREATE_INFO
*
info
);
int
create
(
const
char
*
name
,
TABLE
*
form
,
HA_CREATE_INFO
*
info
);
int
create_handler_files
(
const
char
*
file
,
const
char
*
old_name
,
int
create_handler_files
(
const
char
*
file
,
const
char
*
old_name
,
int
action_flag
,
HA_CREATE_INFO
*
info
);
int
action_flag
,
HA_CREATE_INFO
*
info
);
int
get_default_no_partitions
(
TABLE_SHARE
*
);
int
get_default_no_partitions
(
HA_CREATE_INFO
*
info
);
bool
get_no_parts
(
const
char
*
name
,
uint
*
no_parts
);
bool
get_no_parts
(
const
char
*
name
,
uint
*
no_parts
);
void
set_auto_partitions
(
partition_info
*
part_info
);
void
set_auto_partitions
(
partition_info
*
part_info
);
...
...
sql/handler.h
View file @
9791d534
...
@@ -1335,7 +1335,7 @@ public:
...
@@ -1335,7 +1335,7 @@ public:
virtual
const
char
*
table_type
()
const
=
0
;
virtual
const
char
*
table_type
()
const
=
0
;
virtual
const
char
**
bas_ext
()
const
=
0
;
virtual
const
char
**
bas_ext
()
const
=
0
;
virtual
int
get_default_no_partitions
(
TABLE_SHARE
*
)
{
return
1
;}
virtual
int
get_default_no_partitions
(
HA_CREATE_INFO
*
info
)
{
return
1
;}
virtual
void
set_auto_partitions
(
partition_info
*
part_info
)
{
return
;
}
virtual
void
set_auto_partitions
(
partition_info
*
part_info
)
{
return
;
}
virtual
bool
get_no_parts
(
const
char
*
name
,
virtual
bool
get_no_parts
(
const
char
*
name
,
uint
*
no_parts
)
uint
*
no_parts
)
...
...
sql/partition_info.cc
View file @
9791d534
...
@@ -153,7 +153,7 @@ char *partition_info::create_subpartition_name(uint subpart_no,
...
@@ -153,7 +153,7 @@ char *partition_info::create_subpartition_name(uint subpart_no,
SYNOPSIS
SYNOPSIS
set_up_default_partitions()
set_up_default_partitions()
file A reference to a handler of the table
file A reference to a handler of the table
max_rows Maximum number of rows stored in the table
info Create info
start_no Starting partition number
start_no Starting partition number
RETURN VALUE
RETURN VALUE
...
@@ -169,7 +169,8 @@ char *partition_info::create_subpartition_name(uint subpart_no,
...
@@ -169,7 +169,8 @@ char *partition_info::create_subpartition_name(uint subpart_no,
The external routine needing this code is check_partition_info
The external routine needing this code is check_partition_info
*/
*/
bool
partition_info
::
set_up_default_partitions
(
handler
*
file
,
ulonglong
max_rows
,
bool
partition_info
::
set_up_default_partitions
(
handler
*
file
,
HA_CREATE_INFO
*
info
,
uint
start_no
)
uint
start_no
)
{
{
uint
i
;
uint
i
;
...
@@ -188,7 +189,7 @@ bool partition_info::set_up_default_partitions(handler *file, ulonglong max_rows
...
@@ -188,7 +189,7 @@ bool partition_info::set_up_default_partitions(handler *file, ulonglong max_rows
goto
end
;
goto
end
;
}
}
if
(
no_parts
==
0
)
if
(
no_parts
==
0
)
no_parts
=
file
->
get_default_no_partitions
(
max_rows
);
no_parts
=
file
->
get_default_no_partitions
(
info
);
if
(
unlikely
(
no_parts
>
MAX_PARTITIONS
))
if
(
unlikely
(
no_parts
>
MAX_PARTITIONS
))
{
{
my_error
(
ER_TOO_MANY_PARTITIONS_ERROR
,
MYF
(
0
));
my_error
(
ER_TOO_MANY_PARTITIONS_ERROR
,
MYF
(
0
));
...
@@ -228,7 +229,7 @@ end:
...
@@ -228,7 +229,7 @@ end:
SYNOPSIS
SYNOPSIS
set_up_default_subpartitions()
set_up_default_subpartitions()
file A reference to a handler of the table
file A reference to a handler of the table
max_rows Maximum number of rows stored in the table
info Create info
RETURN VALUE
RETURN VALUE
TRUE Error, attempted default values not possible
TRUE Error, attempted default values not possible
...
@@ -244,7 +245,7 @@ end:
...
@@ -244,7 +245,7 @@ end:
*/
*/
bool
partition_info
::
set_up_default_subpartitions
(
handler
*
file
,
bool
partition_info
::
set_up_default_subpartitions
(
handler
*
file
,
ulonglong
max_rows
)
HA_CREATE_INFO
*
info
)
{
{
uint
i
,
j
;
uint
i
,
j
;
char
*
default_name
,
*
name_ptr
;
char
*
default_name
,
*
name_ptr
;
...
@@ -254,7 +255,7 @@ bool partition_info::set_up_default_subpartitions(handler *file,
...
@@ -254,7 +255,7 @@ bool partition_info::set_up_default_subpartitions(handler *file,
DBUG_ENTER
(
"partition_info::set_up_default_subpartitions"
);
DBUG_ENTER
(
"partition_info::set_up_default_subpartitions"
);
if
(
no_subparts
==
0
)
if
(
no_subparts
==
0
)
no_subparts
=
file
->
get_default_no_partitions
(
max_rows
);
no_subparts
=
file
->
get_default_no_partitions
(
info
);
if
(
unlikely
((
no_parts
*
no_subparts
)
>
MAX_PARTITIONS
))
if
(
unlikely
((
no_parts
*
no_subparts
)
>
MAX_PARTITIONS
))
{
{
my_error
(
ER_TOO_MANY_PARTITIONS_ERROR
,
MYF
(
0
));
my_error
(
ER_TOO_MANY_PARTITIONS_ERROR
,
MYF
(
0
));
...
@@ -296,7 +297,7 @@ end:
...
@@ -296,7 +297,7 @@ end:
SYNOPSIS
SYNOPSIS
set_up_defaults_for_partitioning()
set_up_defaults_for_partitioning()
file A reference to a handler of the table
file A reference to a handler of the table
max_rows Maximum number of rows stored in the table
info Create info
start_no Starting partition number
start_no Starting partition number
RETURN VALUE
RETURN VALUE
...
@@ -309,7 +310,7 @@ end:
...
@@ -309,7 +310,7 @@ end:
*/
*/
bool
partition_info
::
set_up_defaults_for_partitioning
(
handler
*
file
,
bool
partition_info
::
set_up_defaults_for_partitioning
(
handler
*
file
,
ulonglong
max_rows
,
HA_CREATE_INFO
*
info
,
uint
start_no
)
uint
start_no
)
{
{
DBUG_ENTER
(
"partition_info::set_up_defaults_for_partitioning"
);
DBUG_ENTER
(
"partition_info::set_up_defaults_for_partitioning"
);
...
@@ -318,10 +319,10 @@ bool partition_info::set_up_defaults_for_partitioning(handler *file,
...
@@ -318,10 +319,10 @@ bool partition_info::set_up_defaults_for_partitioning(handler *file,
{
{
default_partitions_setup
=
TRUE
;
default_partitions_setup
=
TRUE
;
if
(
use_default_partitions
)
if
(
use_default_partitions
)
DBUG_RETURN
(
set_up_default_partitions
(
file
,
max_rows
,
start_no
));
DBUG_RETURN
(
set_up_default_partitions
(
file
,
info
,
start_no
));
if
(
is_sub_partitioned
()
&&
if
(
is_sub_partitioned
()
&&
use_default_subpartitions
)
use_default_subpartitions
)
DBUG_RETURN
(
set_up_default_subpartitions
(
file
,
max_rows
));
DBUG_RETURN
(
set_up_default_subpartitions
(
file
,
info
));
}
}
DBUG_RETURN
(
FALSE
);
DBUG_RETURN
(
FALSE
);
}
}
...
@@ -692,7 +693,7 @@ end:
...
@@ -692,7 +693,7 @@ end:
SYNOPSIS
SYNOPSIS
check_partition_info()
check_partition_info()
file A reference to a handler of the table
file A reference to a handler of the table
max_rows Maximum number of rows stored in the table
info Create info
engine_type Return value for used engine in partitions
engine_type Return value for used engine in partitions
RETURN VALUE
RETURN VALUE
...
@@ -708,7 +709,7 @@ end:
...
@@ -708,7 +709,7 @@ end:
*/
*/
bool
partition_info
::
check_partition_info
(
THD
*
thd
,
handlerton
**
eng_type
,
bool
partition_info
::
check_partition_info
(
THD
*
thd
,
handlerton
**
eng_type
,
handler
*
file
,
ulonglong
max_rows
)
handler
*
file
,
HA_CREATE_INFO
*
info
)
{
{
handlerton
**
engine_array
=
NULL
;
handlerton
**
engine_array
=
NULL
;
uint
part_count
=
0
;
uint
part_count
=
0
;
...
@@ -743,7 +744,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
...
@@ -743,7 +744,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
my_error
(
ER_SUBPARTITION_ERROR
,
MYF
(
0
));
my_error
(
ER_SUBPARTITION_ERROR
,
MYF
(
0
));
goto
end
;
goto
end
;
}
}
if
(
unlikely
(
set_up_defaults_for_partitioning
(
file
,
max_rows
,
(
uint
)
0
)))
if
(
unlikely
(
set_up_defaults_for_partitioning
(
file
,
info
,
(
uint
)
0
)))
goto
end
;
goto
end
;
tot_partitions
=
get_tot_partitions
();
tot_partitions
=
get_tot_partitions
();
if
(
unlikely
(
tot_partitions
>
MAX_PARTITIONS
))
if
(
unlikely
(
tot_partitions
>
MAX_PARTITIONS
))
...
...
sql/partition_info.h
View file @
9791d534
...
@@ -243,21 +243,21 @@ public:
...
@@ -243,21 +243,21 @@ public:
return
no_parts
*
(
is_sub_partitioned
()
?
no_subparts
:
1
);
return
no_parts
*
(
is_sub_partitioned
()
?
no_subparts
:
1
);
}
}
bool
set_up_defaults_for_partitioning
(
handler
*
file
,
ulonglong
max_rows
,
bool
set_up_defaults_for_partitioning
(
handler
*
file
,
HA_CREATE_INFO
*
info
,
uint
start_no
);
uint
start_no
);
char
*
has_unique_names
();
char
*
has_unique_names
();
static
bool
check_engine_mix
(
handlerton
**
engine_array
,
uint
no_parts
);
static
bool
check_engine_mix
(
handlerton
**
engine_array
,
uint
no_parts
);
bool
check_range_constants
();
bool
check_range_constants
();
bool
check_list_constants
();
bool
check_list_constants
();
bool
check_partition_info
(
THD
*
thd
,
handlerton
**
eng_type
,
bool
check_partition_info
(
THD
*
thd
,
handlerton
**
eng_type
,
handler
*
file
,
ulonglong
max_rows
);
handler
*
file
,
HA_CREATE_INFO
*
info
);
void
print_no_partition_found
(
TABLE
*
table
);
void
print_no_partition_found
(
TABLE
*
table
);
private:
private:
static
int
list_part_cmp
(
const
void
*
a
,
const
void
*
b
);
static
int
list_part_cmp
(
const
void
*
a
,
const
void
*
b
);
static
int
list_part_cmp_unsigned
(
const
void
*
a
,
const
void
*
b
);
static
int
list_part_cmp_unsigned
(
const
void
*
a
,
const
void
*
b
);
bool
set_up_default_partitions
(
handler
*
file
,
ulonglong
max_rows
,
bool
set_up_default_partitions
(
handler
*
file
,
HA_CREATE_INFO
*
info
,
uint
start_no
);
uint
start_no
);
bool
set_up_default_subpartitions
(
handler
*
file
,
ulonglong
max_rows
);
bool
set_up_default_subpartitions
(
handler
*
file
,
HA_CREATE_INFO
*
info
);
char
*
create_default_partition_names
(
uint
part_no
,
uint
no_parts
,
char
*
create_default_partition_names
(
uint
part_no
,
uint
no_parts
,
uint
start_no
);
uint
start_no
);
char
*
create_subpartition_name
(
uint
subpart_no
,
const
char
*
part_name
);
char
*
create_subpartition_name
(
uint
subpart_no
,
const
char
*
part_name
);
...
...
sql/sql_partition.cc
View file @
9791d534
...
@@ -3834,14 +3834,13 @@ uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info,
...
@@ -3834,14 +3834,13 @@ uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info,
if
(
alter_info
->
flags
==
ALTER_TABLE_REORG
)
if
(
alter_info
->
flags
==
ALTER_TABLE_REORG
)
{
{
uint
new_part_no
,
curr_part_no
;
uint
new_part_no
,
curr_part_no
;
ulonglong
max_rows
=
table
->
s
->
max_rows
;
if
(
tab_part_info
->
part_type
!=
HASH_PARTITION
||
if
(
tab_part_info
->
part_type
!=
HASH_PARTITION
||
tab_part_info
->
use_default_no_partitions
)
tab_part_info
->
use_default_no_partitions
)
{
{
my_error
(
ER_REORG_NO_PARAM_ERROR
,
MYF
(
0
));
my_error
(
ER_REORG_NO_PARAM_ERROR
,
MYF
(
0
));
DBUG_RETURN
(
TRUE
);
DBUG_RETURN
(
TRUE
);
}
}
new_part_no
=
table
->
file
->
get_default_no_partitions
(
max_rows
);
new_part_no
=
table
->
file
->
get_default_no_partitions
(
create_info
);
curr_part_no
=
tab_part_info
->
no_parts
;
curr_part_no
=
tab_part_info
->
no_parts
;
if
(
new_part_no
==
curr_part_no
)
if
(
new_part_no
==
curr_part_no
)
{
{
...
...
sql/sql_partition.h
View file @
9791d534
...
@@ -65,7 +65,7 @@ int get_part_for_delete(const byte *buf, const byte *rec0,
...
@@ -65,7 +65,7 @@ int get_part_for_delete(const byte *buf, const byte *rec0,
partition_info
*
part_info
,
uint32
*
part_id
);
partition_info
*
part_info
,
uint32
*
part_id
);
void
prune_partition_set
(
const
TABLE
*
table
,
part_id_range
*
part_spec
);
void
prune_partition_set
(
const
TABLE
*
table
,
part_id_range
*
part_spec
);
bool
check_partition_info
(
partition_info
*
part_info
,
handlerton
**
eng_type
,
bool
check_partition_info
(
partition_info
*
part_info
,
handlerton
**
eng_type
,
TABLE
*
table
,
handler
*
file
,
ulonglong
max_rows
);
TABLE
*
table
,
handler
*
file
,
HA_CREATE_INFO
*
info
);
bool
fix_partition_func
(
THD
*
thd
,
TABLE
*
table
,
bool
create_table_ind
);
bool
fix_partition_func
(
THD
*
thd
,
TABLE
*
table
,
bool
create_table_ind
);
char
*
generate_partition_syntax
(
partition_info
*
part_info
,
char
*
generate_partition_syntax
(
partition_info
*
part_info
,
uint
*
buf_length
,
bool
use_sql_alloc
,
uint
*
buf_length
,
bool
use_sql_alloc
,
...
...
sql/sql_table.cc
View file @
9791d534
...
@@ -3185,8 +3185,7 @@ bool mysql_create_table_internal(THD *thd,
...
@@ -3185,8 +3185,7 @@ bool mysql_create_table_internal(THD *thd,
}
}
DBUG_PRINT
(
"info"
,
(
"db_type = %d"
,
DBUG_PRINT
(
"info"
,
(
"db_type = %d"
,
ha_legacy_type
(
part_info
->
default_engine_type
)));
ha_legacy_type
(
part_info
->
default_engine_type
)));
if
(
part_info
->
check_partition_info
(
thd
,
&
engine_type
,
file
,
if
(
part_info
->
check_partition_info
(
thd
,
&
engine_type
,
file
,
create_info
))
create_info
->
max_rows
))
goto
err
;
goto
err
;
part_info
->
default_engine_type
=
engine_type
;
part_info
->
default_engine_type
=
engine_type
;
...
@@ -3224,7 +3223,8 @@ bool mysql_create_table_internal(THD *thd,
...
@@ -3224,7 +3223,8 @@ bool mysql_create_table_internal(THD *thd,
*/
*/
if
(
part_info
->
use_default_no_partitions
&&
if
(
part_info
->
use_default_no_partitions
&&
part_info
->
no_parts
&&
part_info
->
no_parts
&&
(
int
)
part_info
->
no_parts
!=
file
->
get_default_no_partitions
(
0ULL
))
(
int
)
part_info
->
no_parts
!=
file
->
get_default_no_partitions
(
create_info
))
{
{
uint
i
;
uint
i
;
List_iterator
<
partition_element
>
part_it
(
part_info
->
partitions
);
List_iterator
<
partition_element
>
part_it
(
part_info
->
partitions
);
...
@@ -3237,10 +3237,10 @@ bool mysql_create_table_internal(THD *thd,
...
@@ -3237,10 +3237,10 @@ bool mysql_create_table_internal(THD *thd,
part_info
->
use_default_no_subpartitions
&&
part_info
->
use_default_no_subpartitions
&&
part_info
->
no_subparts
&&
part_info
->
no_subparts
&&
(
int
)
part_info
->
no_subparts
!=
(
int
)
part_info
->
no_subparts
!=
file
->
get_default_no_partitions
(
0ULL
))
file
->
get_default_no_partitions
(
create_info
))
{
{
DBUG_ASSERT
(
thd
->
lex
->
sql_command
!=
SQLCOM_CREATE_TABLE
);
DBUG_ASSERT
(
thd
->
lex
->
sql_command
!=
SQLCOM_CREATE_TABLE
);
part_info
->
no_subparts
=
file
->
get_default_no_partitions
(
0ULL
);
part_info
->
no_subparts
=
file
->
get_default_no_partitions
(
create_info
);
}
}
}
}
else
if
(
create_info
->
db_type
!=
engine_type
)
else
if
(
create_info
->
db_type
!=
engine_type
)
...
...
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