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
d105dc81
Commit
d105dc81
authored
Jun 24, 2010
by
Inaam Rana
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
4cf3e933
79f71e19
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
432 additions
and
127 deletions
+432
-127
mysql-test/suite/innodb_plugin/r/innodb_bug54679.result
mysql-test/suite/innodb_plugin/r/innodb_bug54679.result
+91
-0
mysql-test/suite/innodb_plugin/t/innodb_bug54679.test
mysql-test/suite/innodb_plugin/t/innodb_bug54679.test
+97
-0
storage/innobase/handler/ha_innodb.cc
storage/innobase/handler/ha_innodb.cc
+9
-3
storage/innodb_plugin/ChangeLog
storage/innodb_plugin/ChangeLog
+30
-0
storage/innodb_plugin/dict/dict0dict.c
storage/innodb_plugin/dict/dict0dict.c
+26
-8
storage/innodb_plugin/dict/dict0load.c
storage/innodb_plugin/dict/dict0load.c
+6
-1
storage/innodb_plugin/dict/dict0mem.c
storage/innodb_plugin/dict/dict0mem.c
+3
-1
storage/innodb_plugin/fil/fil0fil.c
storage/innodb_plugin/fil/fil0fil.c
+1
-1
storage/innodb_plugin/handler/ha_innodb.cc
storage/innodb_plugin/handler/ha_innodb.cc
+87
-79
storage/innodb_plugin/include/dict0mem.h
storage/innodb_plugin/include/dict0mem.h
+1
-1
storage/innodb_plugin/include/univ.i
storage/innodb_plugin/include/univ.i
+7
-1
storage/innodb_plugin/page/page0zip.c
storage/innodb_plugin/page/page0zip.c
+1
-0
storage/innodb_plugin/row/row0merge.c
storage/innodb_plugin/row/row0merge.c
+73
-32
No files found.
mysql-test/suite/innodb_plugin/r/innodb_bug54679.result
0 → 100644
View file @
d105dc81
SET GLOBAL innodb_file_format='Barracuda';
SET GLOBAL innodb_file_per_table=ON;
SET innodb_strict_mode=ON;
CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=COMPRESSED;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables
WHERE TABLE_NAME='bug54679';
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
bug54679 Compressed row_format=COMPRESSED
ALTER TABLE bug54679 ADD COLUMN b INT;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables
WHERE TABLE_NAME='bug54679';
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
bug54679 Compressed row_format=COMPRESSED
DROP TABLE bug54679;
CREATE TABLE bug54679 (a INT) ENGINE=InnoDB;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables
WHERE TABLE_NAME='bug54679';
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
bug54679 Compact
ALTER TABLE bug54679 KEY_BLOCK_SIZE=1;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables
WHERE TABLE_NAME='bug54679';
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
bug54679 Compressed KEY_BLOCK_SIZE=1
ALTER TABLE bug54679 ROW_FORMAT=REDUNDANT;
ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
Error 1005 Can't create table '#sql-temporary' (errno: 1478)
DROP TABLE bug54679;
CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables
WHERE TABLE_NAME='bug54679';
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
bug54679 Redundant row_format=REDUNDANT
ALTER TABLE bug54679 KEY_BLOCK_SIZE=2;
SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables
WHERE TABLE_NAME='bug54679';
TABLE_NAME ROW_FORMAT CREATE_OPTIONS
bug54679 Compressed row_format=REDUNDANT KEY_BLOCK_SIZE=2
SET GLOBAL innodb_file_format=Antelope;
ALTER TABLE bug54679 KEY_BLOCK_SIZE=4;
ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Error 1005 Can't create table '#sql-temporary' (errno: 1478)
ALTER TABLE bug54679 ROW_FORMAT=DYNAMIC;
ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope.
Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
Error 1005 Can't create table '#sql-temporary' (errno: 1478)
DROP TABLE bug54679;
CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
ERROR HY000: Can't create table 'test.bug54679' (errno: 1478)
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope.
Error 1005 Can't create table 'test.bug54679' (errno: 1478)
CREATE TABLE bug54679 (a INT) ENGINE=InnoDB;
SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=OFF;
ALTER TABLE bug54679 KEY_BLOCK_SIZE=4;
ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table '#sql-temporary' (errno: 1478)
ALTER TABLE bug54679 ROW_FORMAT=DYNAMIC;
ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
Error 1005 Can't create table '#sql-temporary' (errno: 1478)
DROP TABLE bug54679;
CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
ERROR HY000: Can't create table 'test.bug54679' (errno: 1478)
SHOW WARNINGS;
Level Code Message
Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
Error 1005 Can't create table 'test.bug54679' (errno: 1478)
SET GLOBAL innodb_file_per_table=ON;
CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
DROP TABLE bug54679;
SET GLOBAL innodb_file_format=Antelope;
SET GLOBAL innodb_file_format_check=Antelope;
SET GLOBAL innodb_file_per_table=0;
mysql-test/suite/innodb_plugin/t/innodb_bug54679.test
0 → 100644
View file @
d105dc81
# Test Bug #54679 alter table causes compressed row_format to revert to compact
--
source
include
/
have_innodb_plugin
.
inc
let
$file_format
=
`select @@innodb_file_format`
;
let
$file_format_check
=
`select @@innodb_file_format_check`
;
let
$file_per_table
=
`select @@innodb_file_per_table`
;
SET
GLOBAL
innodb_file_format
=
'Barracuda'
;
SET
GLOBAL
innodb_file_per_table
=
ON
;
SET
innodb_strict_mode
=
ON
;
CREATE
TABLE
bug54679
(
a
INT
)
ENGINE
=
InnoDB
ROW_FORMAT
=
COMPRESSED
;
SELECT
TABLE_NAME
,
ROW_FORMAT
,
CREATE_OPTIONS
FROM
information_schema
.
tables
WHERE
TABLE_NAME
=
'bug54679'
;
# The ROW_FORMAT of the table should be preserved when it is not specified
# in ALTER TABLE.
ALTER
TABLE
bug54679
ADD
COLUMN
b
INT
;
SELECT
TABLE_NAME
,
ROW_FORMAT
,
CREATE_OPTIONS
FROM
information_schema
.
tables
WHERE
TABLE_NAME
=
'bug54679'
;
DROP
TABLE
bug54679
;
# Check that the ROW_FORMAT conversion to/from COMPRESSED works.
CREATE
TABLE
bug54679
(
a
INT
)
ENGINE
=
InnoDB
;
SELECT
TABLE_NAME
,
ROW_FORMAT
,
CREATE_OPTIONS
FROM
information_schema
.
tables
WHERE
TABLE_NAME
=
'bug54679'
;
# KEY_BLOCK_SIZE implies COMPRESSED.
ALTER
TABLE
bug54679
KEY_BLOCK_SIZE
=
1
;
SELECT
TABLE_NAME
,
ROW_FORMAT
,
CREATE_OPTIONS
FROM
information_schema
.
tables
WHERE
TABLE_NAME
=
'bug54679'
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
--
error
ER_CANT_CREATE_TABLE
ALTER
TABLE
bug54679
ROW_FORMAT
=
REDUNDANT
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW
WARNINGS
;
DROP
TABLE
bug54679
;
CREATE
TABLE
bug54679
(
a
INT
)
ENGINE
=
InnoDB
ROW_FORMAT
=
REDUNDANT
;
SELECT
TABLE_NAME
,
ROW_FORMAT
,
CREATE_OPTIONS
FROM
information_schema
.
tables
WHERE
TABLE_NAME
=
'bug54679'
;
ALTER
TABLE
bug54679
KEY_BLOCK_SIZE
=
2
;
SELECT
TABLE_NAME
,
ROW_FORMAT
,
CREATE_OPTIONS
FROM
information_schema
.
tables
WHERE
TABLE_NAME
=
'bug54679'
;
# This prevents other than REDUNDANT or COMPACT ROW_FORMAT for new tables.
SET
GLOBAL
innodb_file_format
=
Antelope
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
--
error
ER_CANT_CREATE_TABLE
ALTER
TABLE
bug54679
KEY_BLOCK_SIZE
=
4
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW
WARNINGS
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
--
error
ER_CANT_CREATE_TABLE
ALTER
TABLE
bug54679
ROW_FORMAT
=
DYNAMIC
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW
WARNINGS
;
DROP
TABLE
bug54679
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
--
error
ER_CANT_CREATE_TABLE
CREATE
TABLE
bug54679
(
a
INT
)
ENGINE
=
InnoDB
ROW_FORMAT
=
DYNAMIC
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW
WARNINGS
;
CREATE
TABLE
bug54679
(
a
INT
)
ENGINE
=
InnoDB
;
SET
GLOBAL
innodb_file_format
=
Barracuda
;
# This will prevent ROW_FORMAT=COMPRESSED, because the system tablespace
# cannot be compressed.
SET
GLOBAL
innodb_file_per_table
=
OFF
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
--
error
ER_CANT_CREATE_TABLE
ALTER
TABLE
bug54679
KEY_BLOCK_SIZE
=
4
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW
WARNINGS
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
--
error
ER_CANT_CREATE_TABLE
ALTER
TABLE
bug54679
ROW_FORMAT
=
DYNAMIC
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW
WARNINGS
;
DROP
TABLE
bug54679
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
--
error
ER_CANT_CREATE_TABLE
CREATE
TABLE
bug54679
(
a
INT
)
ENGINE
=
InnoDB
ROW_FORMAT
=
DYNAMIC
;
--
replace_regex
/
'[^'
]
*
test
\
.
#sql-[0-9a-f_]*'/'#sql-temporary'/
SHOW
WARNINGS
;
SET
GLOBAL
innodb_file_per_table
=
ON
;
CREATE
TABLE
bug54679
(
a
INT
)
ENGINE
=
InnoDB
ROW_FORMAT
=
DYNAMIC
;
DROP
TABLE
bug54679
;
EVAL
SET
GLOBAL
innodb_file_format
=
$file_format
;
EVAL
SET
GLOBAL
innodb_file_format_check
=
$file_format_check
;
EVAL
SET
GLOBAL
innodb_file_per_table
=
$file_per_table
;
storage/innobase/handler/ha_innodb.cc
View file @
d105dc81
...
@@ -583,13 +583,13 @@ thd_is_select(
...
@@ -583,13 +583,13 @@ thd_is_select(
/************************************************************************
/************************************************************************
Obtain the InnoDB transaction of a MySQL thread. */
Obtain the InnoDB transaction of a MySQL thread. */
inline
inline
trx_t
*
&
trx_t
*
thd_to_trx
(
thd_to_trx
(
/*=======*/
/*=======*/
/* out: reference to transaction pointer */
/* out: reference to transaction pointer */
THD
*
thd
)
/* in: MySQL thread */
THD
*
thd
)
/* in: MySQL thread */
{
{
return
(
*
(
trx_t
**
)
thd
_ha_data
(
thd
,
innodb_hton_ptr
));
return
(
(
trx_t
*
)
thd_get
_ha_data
(
thd
,
innodb_hton_ptr
));
}
}
/************************************************************************
/************************************************************************
...
@@ -1164,7 +1164,7 @@ check_trx_exists(
...
@@ -1164,7 +1164,7 @@ check_trx_exists(
/* out: InnoDB transaction handle */
/* out: InnoDB transaction handle */
THD
*
thd
)
/* in: user thread handle */
THD
*
thd
)
/* in: user thread handle */
{
{
trx_t
*
&
trx
=
thd_to_trx
(
thd
);
trx_t
*
trx
=
thd_to_trx
(
thd
);
ut_ad
(
thd
==
current_thd
);
ut_ad
(
thd
==
current_thd
);
...
@@ -1178,6 +1178,9 @@ check_trx_exists(
...
@@ -1178,6 +1178,9 @@ check_trx_exists(
/* Update the info whether we should skip XA steps that eat
/* Update the info whether we should skip XA steps that eat
CPU time */
CPU time */
trx
->
support_xa
=
THDVAR
(
thd
,
support_xa
);
trx
->
support_xa
=
THDVAR
(
thd
,
support_xa
);
/* We have a new trx, register with the thread handle */
thd_set_ha_data
(
thd
,
innodb_hton_ptr
,
trx
);
}
else
{
}
else
{
if
(
trx
->
magic_n
!=
TRX_MAGIC_N
)
{
if
(
trx
->
magic_n
!=
TRX_MAGIC_N
)
{
mem_analyze_corruption
(
trx
);
mem_analyze_corruption
(
trx
);
...
@@ -2482,6 +2485,9 @@ innobase_close_connection(
...
@@ -2482,6 +2485,9 @@ innobase_close_connection(
innobase_rollback_trx
(
trx
);
innobase_rollback_trx
(
trx
);
/* Release the lock in thread handler */
thd_set_ha_data
(
thd
,
hton
,
NULL
);
thr_local_free
(
trx
->
mysql_thread_id
);
thr_local_free
(
trx
->
mysql_thread_id
);
trx_free_for_mysql
(
trx
);
trx_free_for_mysql
(
trx
);
...
...
storage/innodb_plugin/ChangeLog
View file @
d105dc81
2010-06-24 The InnoDB Team
* handler/ha_innodb.cc:
Fix Bug#54679 alter table causes compressed row_format to revert
to compact
2010-06-22 The InnoDB Team
* dict/dict0dict.c, dict/dict0mem.c, include/dict0mem.h,
include/univ.i, page/page0zip.c, row/row0merge.c:
Fix Bug#47991 InnoDB Dictionary Cache memory usage increases
indefinitely when renaming tables
2010-06-22 The InnoDB Team
* handler/ha_innodb.cc:
Fix Bug#54686: "field->col->mtype == type" assertion error at
row/row0sel.c
2010-06-21 The InnoDB Team
* dict/dict0load.c, fil/fil0fil.c:
Fix Bug#54658: InnoDB: Warning: allocated tablespace %lu,
old maximum was 0 (introduced in Bug #53578 fix)
2010-06-16 The InnoDB Team
* row/row0merge.c:
Fix Bug#54330 Broken fast index creation
2010-06-10 The InnoDB Team
2010-06-10 The InnoDB Team
* include/log0log.ic, row/row0ins.c, row/row0purge.c,
* include/log0log.ic, row/row0ins.c, row/row0purge.c,
...
...
storage/innodb_plugin/dict/dict0dict.c
View file @
d105dc81
...
@@ -850,7 +850,8 @@ dict_table_add_to_cache(
...
@@ -850,7 +850,8 @@ dict_table_add_to_cache(
/* Add table to LRU list of tables */
/* Add table to LRU list of tables */
UT_LIST_ADD_FIRST
(
table_LRU
,
dict_sys
->
table_LRU
,
table
);
UT_LIST_ADD_FIRST
(
table_LRU
,
dict_sys
->
table_LRU
,
table
);
dict_sys
->
size
+=
mem_heap_get_size
(
table
->
heap
);
dict_sys
->
size
+=
mem_heap_get_size
(
table
->
heap
)
+
strlen
(
table
->
name
)
+
1
;
}
}
/**********************************************************************//**
/**********************************************************************//**
...
@@ -904,14 +905,21 @@ dict_table_rename_in_cache(
...
@@ -904,14 +905,21 @@ dict_table_rename_in_cache(
dict_foreign_t
*
foreign
;
dict_foreign_t
*
foreign
;
dict_index_t
*
index
;
dict_index_t
*
index
;
ulint
fold
;
ulint
fold
;
ulint
old_size
;
char
old_name
[
MAX_TABLE_NAME_LEN
+
1
];
const
char
*
old_name
;
ut_ad
(
table
);
ut_ad
(
table
);
ut_ad
(
mutex_own
(
&
(
dict_sys
->
mutex
)));
ut_ad
(
mutex_own
(
&
(
dict_sys
->
mutex
)));
old_size
=
mem_heap_get_size
(
table
->
heap
);
/* store the old/current name to an automatic variable */
old_name
=
table
->
name
;
if
(
strlen
(
table
->
name
)
+
1
<=
sizeof
(
old_name
))
{
memcpy
(
old_name
,
table
->
name
,
strlen
(
table
->
name
)
+
1
);
}
else
{
ut_print_timestamp
(
stderr
);
fprintf
(
stderr
,
"InnoDB: too long table name: '%s', "
"max length is %d
\n
"
,
table
->
name
,
MAX_TABLE_NAME_LEN
);
ut_error
;
}
fold
=
ut_fold_string
(
new_name
);
fold
=
ut_fold_string
(
new_name
);
...
@@ -957,12 +965,22 @@ dict_table_rename_in_cache(
...
@@ -957,12 +965,22 @@ dict_table_rename_in_cache(
/* Remove table from the hash tables of tables */
/* Remove table from the hash tables of tables */
HASH_DELETE
(
dict_table_t
,
name_hash
,
dict_sys
->
table_hash
,
HASH_DELETE
(
dict_table_t
,
name_hash
,
dict_sys
->
table_hash
,
ut_fold_string
(
old_name
),
table
);
ut_fold_string
(
old_name
),
table
);
table
->
name
=
mem_heap_strdup
(
table
->
heap
,
new_name
);
if
(
strlen
(
new_name
)
>
strlen
(
table
->
name
))
{
/* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid
memory fragmentation, we assume a repeated calls of
ut_realloc() with the same size do not cause fragmentation */
ut_a
(
strlen
(
new_name
)
<=
MAX_TABLE_NAME_LEN
);
table
->
name
=
ut_realloc
(
table
->
name
,
MAX_TABLE_NAME_LEN
+
1
);
}
memcpy
(
table
->
name
,
new_name
,
strlen
(
new_name
)
+
1
);
/* Add table to hash table of tables */
/* Add table to hash table of tables */
HASH_INSERT
(
dict_table_t
,
name_hash
,
dict_sys
->
table_hash
,
fold
,
HASH_INSERT
(
dict_table_t
,
name_hash
,
dict_sys
->
table_hash
,
fold
,
table
);
table
);
dict_sys
->
size
+=
(
mem_heap_get_size
(
table
->
heap
)
-
old_size
);
dict_sys
->
size
+=
strlen
(
new_name
)
-
strlen
(
old_name
);
ut_a
(
dict_sys
->
size
>
0
);
/* Update the table_name field in indexes */
/* Update the table_name field in indexes */
index
=
dict_table_get_first_index
(
table
);
index
=
dict_table_get_first_index
(
table
);
...
@@ -1187,7 +1205,7 @@ dict_table_remove_from_cache(
...
@@ -1187,7 +1205,7 @@ dict_table_remove_from_cache(
/* Remove table from LRU list of tables */
/* Remove table from LRU list of tables */
UT_LIST_REMOVE
(
table_LRU
,
dict_sys
->
table_LRU
,
table
);
UT_LIST_REMOVE
(
table_LRU
,
dict_sys
->
table_LRU
,
table
);
size
=
mem_heap_get_size
(
table
->
heap
);
size
=
mem_heap_get_size
(
table
->
heap
)
+
strlen
(
table
->
name
)
+
1
;
ut_ad
(
dict_sys
->
size
>=
size
);
ut_ad
(
dict_sys
->
size
>=
size
);
...
...
storage/innodb_plugin/dict/dict0load.c
View file @
d105dc81
...
@@ -316,7 +316,7 @@ dict_check_tablespaces_and_store_max_id(
...
@@ -316,7 +316,7 @@ dict_check_tablespaces_and_store_max_id(
dict_index_t
*
sys_index
;
dict_index_t
*
sys_index
;
btr_pcur_t
pcur
;
btr_pcur_t
pcur
;
const
rec_t
*
rec
;
const
rec_t
*
rec
;
ulint
max_space_id
=
0
;
ulint
max_space_id
;
mtr_t
mtr
;
mtr_t
mtr
;
mutex_enter
(
&
(
dict_sys
->
mutex
));
mutex_enter
(
&
(
dict_sys
->
mutex
));
...
@@ -327,6 +327,11 @@ dict_check_tablespaces_and_store_max_id(
...
@@ -327,6 +327,11 @@ dict_check_tablespaces_and_store_max_id(
sys_index
=
UT_LIST_GET_FIRST
(
sys_tables
->
indexes
);
sys_index
=
UT_LIST_GET_FIRST
(
sys_tables
->
indexes
);
ut_a
(
!
dict_table_is_comp
(
sys_tables
));
ut_a
(
!
dict_table_is_comp
(
sys_tables
));
max_space_id
=
mtr_read_ulint
(
dict_hdr_get
(
&
mtr
)
+
DICT_HDR_MAX_SPACE_ID
,
MLOG_4BYTES
,
&
mtr
);
fil_set_max_space_id_if_bigger
(
max_space_id
);
btr_pcur_open_at_index_side
(
TRUE
,
sys_index
,
BTR_SEARCH_LEAF
,
&
pcur
,
btr_pcur_open_at_index_side
(
TRUE
,
sys_index
,
BTR_SEARCH_LEAF
,
&
pcur
,
TRUE
,
&
mtr
);
TRUE
,
&
mtr
);
loop:
loop:
...
...
storage/innodb_plugin/dict/dict0mem.c
View file @
d105dc81
...
@@ -68,7 +68,8 @@ dict_mem_table_create(
...
@@ -68,7 +68,8 @@ dict_mem_table_create(
table
->
heap
=
heap
;
table
->
heap
=
heap
;
table
->
flags
=
(
unsigned
int
)
flags
;
table
->
flags
=
(
unsigned
int
)
flags
;
table
->
name
=
mem_heap_strdup
(
heap
,
name
);
table
->
name
=
ut_malloc
(
strlen
(
name
)
+
1
);
memcpy
(
table
->
name
,
name
,
strlen
(
name
)
+
1
);
table
->
space
=
(
unsigned
int
)
space
;
table
->
space
=
(
unsigned
int
)
space
;
table
->
n_cols
=
(
unsigned
int
)
(
n_cols
+
DATA_N_SYS_COLS
);
table
->
n_cols
=
(
unsigned
int
)
(
n_cols
+
DATA_N_SYS_COLS
);
...
@@ -106,6 +107,7 @@ dict_mem_table_free(
...
@@ -106,6 +107,7 @@ dict_mem_table_free(
#ifndef UNIV_HOTBACKUP
#ifndef UNIV_HOTBACKUP
mutex_free
(
&
(
table
->
autoinc_mutex
));
mutex_free
(
&
(
table
->
autoinc_mutex
));
#endif
/* UNIV_HOTBACKUP */
#endif
/* UNIV_HOTBACKUP */
ut_free
(
table
->
name
);
mem_heap_free
(
table
->
heap
);
mem_heap_free
(
table
->
heap
);
}
}
...
...
storage/innodb_plugin/fil/fil0fil.c
View file @
d105dc81
...
@@ -1197,7 +1197,7 @@ fil_space_create(
...
@@ -1197,7 +1197,7 @@ fil_space_create(
space
->
tablespace_version
=
fil_system
->
tablespace_version
;
space
->
tablespace_version
=
fil_system
->
tablespace_version
;
space
->
mark
=
FALSE
;
space
->
mark
=
FALSE
;
if
(
UNIV_LIKELY
(
purpose
==
FIL_TABLESPACE
)
if
(
UNIV_LIKELY
(
purpose
==
FIL_TABLESPACE
&&
!
recv_recovery_on
)
&&
UNIV_UNLIKELY
(
id
>
fil_system
->
max_assigned_id
))
{
&&
UNIV_UNLIKELY
(
id
>
fil_system
->
max_assigned_id
))
{
if
(
!
fil_system
->
space_id_reuse_warned
)
{
if
(
!
fil_system
->
space_id_reuse_warned
)
{
fil_system
->
space_id_reuse_warned
=
TRUE
;
fil_system
->
space_id_reuse_warned
=
TRUE
;
...
...
storage/innodb_plugin/handler/ha_innodb.cc
View file @
d105dc81
...
@@ -5379,6 +5379,9 @@ ha_innobase::index_read(
...
@@ -5379,6 +5379,9 @@ ha_innobase::index_read(
prebuilt
->
index_usable
=
FALSE
;
prebuilt
->
index_usable
=
FALSE
;
DBUG_RETURN
(
HA_ERR_CRASHED
);
DBUG_RETURN
(
HA_ERR_CRASHED
);
}
}
if
(
UNIV_UNLIKELY
(
!
prebuilt
->
index_usable
))
{
DBUG_RETURN
(
HA_ERR_TABLE_DEF_CHANGED
);
}
/* Note that if the index for which the search template is built is not
/* Note that if the index for which the search template is built is not
necessarily prebuilt->index, but can also be the clustered index */
necessarily prebuilt->index, but can also be the clustered index */
...
@@ -6457,6 +6460,7 @@ ha_innobase::create(
...
@@ -6457,6 +6460,7 @@ ha_innobase::create(
const
ulint
file_format
=
srv_file_format
;
const
ulint
file_format
=
srv_file_format
;
const
char
*
stmt
;
const
char
*
stmt
;
size_t
stmt_len
;
size_t
stmt_len
;
enum
row_type
row_type
;
DBUG_ENTER
(
"ha_innobase::create"
);
DBUG_ENTER
(
"ha_innobase::create"
);
...
@@ -6577,10 +6581,15 @@ ha_innobase::create(
...
@@ -6577,10 +6581,15 @@ ha_innobase::create(
}
}
}
}
if
(
create_info
->
used_fields
&
HA_CREATE_USED_ROW_FORMAT
)
{
row_type
=
form
->
s
->
row_type
;
if
(
flags
)
{
if
(
flags
)
{
/* KEY_BLOCK_SIZE was specified. */
/* KEY_BLOCK_SIZE was specified. */
if
(
form
->
s
->
row_type
!=
ROW_TYPE_COMPRESSED
)
{
if
(
!
(
create_info
->
used_fields
&
HA_CREATE_USED_ROW_FORMAT
))
{
/* ROW_FORMAT was not specified;
default to ROW_FORMAT=COMPRESSED */
row_type
=
ROW_TYPE_COMPRESSED
;
}
else
if
(
row_type
!=
ROW_TYPE_COMPRESSED
)
{
/* ROW_FORMAT other than COMPRESSED
/* ROW_FORMAT other than COMPRESSED
ignores KEY_BLOCK_SIZE. It does not
ignores KEY_BLOCK_SIZE. It does not
make sense to reject conflicting
make sense to reject conflicting
...
@@ -6598,7 +6607,7 @@ ha_innobase::create(
...
@@ -6598,7 +6607,7 @@ ha_innobase::create(
}
}
}
else
{
}
else
{
/* No KEY_BLOCK_SIZE */
/* No KEY_BLOCK_SIZE */
if
(
form
->
s
->
row_type
==
ROW_TYPE_COMPRESSED
)
{
if
(
row_type
==
ROW_TYPE_COMPRESSED
)
{
/* ROW_FORMAT=COMPRESSED without
/* ROW_FORMAT=COMPRESSED without
KEY_BLOCK_SIZE implies half the
KEY_BLOCK_SIZE implies half the
maximum KEY_BLOCK_SIZE. */
maximum KEY_BLOCK_SIZE. */
...
@@ -6613,14 +6622,14 @@ ha_innobase::create(
...
@@ -6613,14 +6622,14 @@ ha_innobase::create(
}
}
}
}
switch
(
form
->
s
->
row_type
)
{
switch
(
row_type
)
{
const
char
*
row_format_name
;
const
char
*
row_format_name
;
case
ROW_TYPE_REDUNDANT
:
case
ROW_TYPE_REDUNDANT
:
break
;
break
;
case
ROW_TYPE_COMPRESSED
:
case
ROW_TYPE_COMPRESSED
:
case
ROW_TYPE_DYNAMIC
:
case
ROW_TYPE_DYNAMIC
:
row_format_name
row_format_name
=
form
->
s
->
row_type
==
ROW_TYPE_COMPRESSED
=
row_type
==
ROW_TYPE_COMPRESSED
?
"COMPRESSED"
?
"COMPRESSED"
:
"DYNAMIC"
;
:
"DYNAMIC"
;
...
@@ -6661,11 +6670,6 @@ ha_innobase::create(
...
@@ -6661,11 +6670,6 @@ ha_innobase::create(
flags
=
DICT_TF_COMPACT
;
flags
=
DICT_TF_COMPACT
;
break
;
break
;
}
}
}
else
if
(
!
flags
)
{
/* No KEY_BLOCK_SIZE or ROW_FORMAT specified:
use ROW_FORMAT=COMPACT by default. */
flags
=
DICT_TF_COMPACT
;
}
/* Look for a primary key */
/* Look for a primary key */
...
@@ -7221,6 +7225,10 @@ ha_innobase::records_in_range(
...
@@ -7221,6 +7225,10 @@ ha_innobase::records_in_range(
n_rows
=
HA_POS_ERROR
;
n_rows
=
HA_POS_ERROR
;
goto
func_exit
;
goto
func_exit
;
}
}
if
(
UNIV_UNLIKELY
(
!
row_merge_is_index_usable
(
prebuilt
->
trx
,
index
)))
{
n_rows
=
HA_ERR_TABLE_DEF_CHANGED
;
goto
func_exit
;
}
heap
=
mem_heap_create
(
2
*
(
key
->
key_parts
*
sizeof
(
dfield_t
)
heap
=
mem_heap_create
(
2
*
(
key
->
key_parts
*
sizeof
(
dfield_t
)
+
sizeof
(
dtuple_t
)));
+
sizeof
(
dtuple_t
)));
...
...
storage/innodb_plugin/include/dict0mem.h
View file @
d105dc81
...
@@ -382,7 +382,7 @@ initialized to 0, NULL or FALSE in dict_mem_table_create(). */
...
@@ -382,7 +382,7 @@ initialized to 0, NULL or FALSE in dict_mem_table_create(). */
struct
dict_table_struct
{
struct
dict_table_struct
{
dulint
id
;
/*!< id of the table */
dulint
id
;
/*!< id of the table */
mem_heap_t
*
heap
;
/*!< memory heap */
mem_heap_t
*
heap
;
/*!< memory heap */
c
onst
char
*
name
;
/*!< table name */
c
har
*
name
;
/*!< table name */
const
char
*
dir_path_of_temp_table
;
/*!< NULL or the directory path
const
char
*
dir_path_of_temp_table
;
/*!< NULL or the directory path
where a TEMPORARY table that was explicitly
where a TEMPORARY table that was explicitly
created by a user should be placed if
created by a user should be placed if
...
...
storage/innodb_plugin/include/univ.i
View file @
d105dc81
...
@@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri
...
@@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri
#
define
INNODB_VERSION_MAJOR
1
#
define
INNODB_VERSION_MAJOR
1
#
define
INNODB_VERSION_MINOR
0
#
define
INNODB_VERSION_MINOR
0
#
define
INNODB_VERSION_BUGFIX
9
#
define
INNODB_VERSION_BUGFIX
10
/* The following is the InnoDB version as shown in
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
SELECT plugin_version FROM information_schema.plugins;
...
@@ -290,6 +290,12 @@ management to ensure correct alignment for doubles etc. */
...
@@ -290,6 +290,12 @@ management to ensure correct alignment for doubles etc. */
/* Maximum number of parallel threads in a parallelized operation */
/* Maximum number of parallel threads in a parallelized operation */
#
define
UNIV_MAX_PARALLELISM
32
#
define
UNIV_MAX_PARALLELISM
32
/* The maximum length of a table name. This is the MySQL limit and is
defined in mysql_com.h like NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN, the
number does not include a terminating '\0'. InnoDB probably can handle
longer names internally */
#
define
MAX_TABLE_NAME_LEN
192
/*
/*
UNIVERSAL TYPE DEFINITIONS
UNIVERSAL TYPE DEFINITIONS
==========================
==========================
...
...
storage/innodb_plugin/page/page0zip.c
View file @
d105dc81
...
@@ -1464,6 +1464,7 @@ page_zip_fields_free(
...
@@ -1464,6 +1464,7 @@ page_zip_fields_free(
dict_table_t
*
table
=
index
->
table
;
dict_table_t
*
table
=
index
->
table
;
mem_heap_free
(
index
->
heap
);
mem_heap_free
(
index
->
heap
);
mutex_free
(
&
(
table
->
autoinc_mutex
));
mutex_free
(
&
(
table
->
autoinc_mutex
));
ut_free
(
table
->
name
);
mem_heap_free
(
table
->
heap
);
mem_heap_free
(
table
->
heap
);
}
}
}
}
...
...
storage/innodb_plugin/row/row0merge.c
View file @
d105dc81
...
@@ -1578,22 +1578,28 @@ row_merge(
...
@@ -1578,22 +1578,28 @@ row_merge(
const
dict_index_t
*
index
,
/*!< in: index being created */
const
dict_index_t
*
index
,
/*!< in: index being created */
merge_file_t
*
file
,
/*!< in/out: file containing
merge_file_t
*
file
,
/*!< in/out: file containing
index entries */
index entries */
ulint
*
half
,
/*!< in/out: half the file */
row_merge_block_t
*
block
,
/*!< in/out: 3 buffers */
row_merge_block_t
*
block
,
/*!< in/out: 3 buffers */
int
*
tmpfd
,
/*!< in/out: temporary file handle */
int
*
tmpfd
,
/*!< in/out: temporary file handle */
TABLE
*
table
)
/*!< in/out: MySQL table, for
TABLE
*
table
,
/*!< in/out: MySQL table, for
reporting erroneous key value
reporting erroneous key value
if applicable */
if applicable */
ulint
*
num_run
,
/*!< in/out: Number of runs remain
to be merged */
ulint
*
run_offset
)
/*!< in/out: Array contains the
first offset number for each merge
run */
{
{
ulint
foffs0
;
/*!< first input offset */
ulint
foffs0
;
/*!< first input offset */
ulint
foffs1
;
/*!< second input offset */
ulint
foffs1
;
/*!< second input offset */
ulint
error
;
/*!< error code */
ulint
error
;
/*!< error code */
merge_file_t
of
;
/*!< output file */
merge_file_t
of
;
/*!< output file */
const
ulint
ihalf
=
*
half
;
const
ulint
ihalf
=
run_offset
[
*
num_run
/
2
]
;
/*!< half the input file */
/*!< half the input file */
ulint
ohalf
;
/*!< half the output file */
ulint
n_run
=
0
;
/*!< num of runs generated from this merge */
UNIV_MEM_ASSERT_W
(
block
[
0
],
3
*
sizeof
block
[
0
]);
UNIV_MEM_ASSERT_W
(
block
[
0
],
3
*
sizeof
block
[
0
]);
ut_ad
(
ihalf
<
file
->
offset
);
ut_ad
(
ihalf
<
file
->
offset
);
of
.
fd
=
*
tmpfd
;
of
.
fd
=
*
tmpfd
;
...
@@ -1601,17 +1607,20 @@ row_merge(
...
@@ -1601,17 +1607,20 @@ row_merge(
of
.
n_rec
=
0
;
of
.
n_rec
=
0
;
/* Merge blocks to the output file. */
/* Merge blocks to the output file. */
ohalf
=
0
;
foffs0
=
0
;
foffs0
=
0
;
foffs1
=
ihalf
;
foffs1
=
ihalf
;
UNIV_MEM_INVALID
(
run_offset
,
*
num_run
*
sizeof
*
run_offset
);
for
(;
foffs0
<
ihalf
&&
foffs1
<
file
->
offset
;
foffs0
++
,
foffs1
++
)
{
for
(;
foffs0
<
ihalf
&&
foffs1
<
file
->
offset
;
foffs0
++
,
foffs1
++
)
{
ulint
ahalf
;
/*!< arithmetic half the input file */
if
(
UNIV_UNLIKELY
(
trx_is_interrupted
(
trx
)))
{
if
(
UNIV_UNLIKELY
(
trx_is_interrupted
(
trx
)))
{
return
(
DB_INTERRUPTED
);
return
(
DB_INTERRUPTED
);
}
}
/* Remember the offset number for this run */
run_offset
[
n_run
++
]
=
of
.
offset
;
error
=
row_merge_blocks
(
index
,
file
,
block
,
error
=
row_merge_blocks
(
index
,
file
,
block
,
&
foffs0
,
&
foffs1
,
&
of
,
table
);
&
foffs0
,
&
foffs1
,
&
of
,
table
);
...
@@ -1619,21 +1628,6 @@ row_merge(
...
@@ -1619,21 +1628,6 @@ row_merge(
return
(
error
);
return
(
error
);
}
}
/* Record the offset of the output file when
approximately half the output has been generated. In
this way, the next invocation of row_merge() will
spend most of the time in this loop. The initial
estimate is ohalf==0. */
ahalf
=
file
->
offset
/
2
;
ut_ad
(
ohalf
<=
of
.
offset
);
/* Improve the estimate until reaching half the input
file size, or we can not get any closer to it. All
comparands should be non-negative when !(ohalf < ahalf)
because ohalf <= of.offset. */
if
(
ohalf
<
ahalf
||
of
.
offset
-
ahalf
<
ohalf
-
ahalf
)
{
ohalf
=
of
.
offset
;
}
}
}
/* Copy the last blocks, if there are any. */
/* Copy the last blocks, if there are any. */
...
@@ -1643,6 +1637,9 @@ row_merge(
...
@@ -1643,6 +1637,9 @@ row_merge(
return
(
DB_INTERRUPTED
);
return
(
DB_INTERRUPTED
);
}
}
/* Remember the offset number for this run */
run_offset
[
n_run
++
]
=
of
.
offset
;
if
(
!
row_merge_blocks_copy
(
index
,
file
,
block
,
&
foffs0
,
&
of
))
{
if
(
!
row_merge_blocks_copy
(
index
,
file
,
block
,
&
foffs0
,
&
of
))
{
return
(
DB_CORRUPTION
);
return
(
DB_CORRUPTION
);
}
}
...
@@ -1655,6 +1652,9 @@ row_merge(
...
@@ -1655,6 +1652,9 @@ row_merge(
return
(
DB_INTERRUPTED
);
return
(
DB_INTERRUPTED
);
}
}
/* Remember the offset number for this run */
run_offset
[
n_run
++
]
=
of
.
offset
;
if
(
!
row_merge_blocks_copy
(
index
,
file
,
block
,
&
foffs1
,
&
of
))
{
if
(
!
row_merge_blocks_copy
(
index
,
file
,
block
,
&
foffs1
,
&
of
))
{
return
(
DB_CORRUPTION
);
return
(
DB_CORRUPTION
);
}
}
...
@@ -1666,10 +1666,23 @@ row_merge(
...
@@ -1666,10 +1666,23 @@ row_merge(
return
(
DB_CORRUPTION
);
return
(
DB_CORRUPTION
);
}
}
ut_ad
(
n_run
<=
*
num_run
);
*
num_run
=
n_run
;
/* Each run can contain one or more offsets. As merge goes on,
the number of runs (to merge) will reduce until we have one
single run. So the number of runs will always be smaller than
the number of offsets in file */
ut_ad
((
*
num_run
)
<=
file
->
offset
);
/* The number of offsets in output file is always equal or
smaller than input file */
ut_ad
(
of
.
offset
<=
file
->
offset
);
/* Swap file descriptors for the next pass. */
/* Swap file descriptors for the next pass. */
*
tmpfd
=
file
->
fd
;
*
tmpfd
=
file
->
fd
;
*
file
=
of
;
*
file
=
of
;
*
half
=
ohalf
;
UNIV_MEM_INVALID
(
block
[
0
],
3
*
sizeof
block
[
0
]);
UNIV_MEM_INVALID
(
block
[
0
],
3
*
sizeof
block
[
0
]);
...
@@ -1694,27 +1707,44 @@ row_merge_sort(
...
@@ -1694,27 +1707,44 @@ row_merge_sort(
if applicable */
if applicable */
{
{
ulint
half
=
file
->
offset
/
2
;
ulint
half
=
file
->
offset
/
2
;
ulint
num_runs
;
ulint
*
run_offset
;
ulint
error
=
DB_SUCCESS
;
/* Record the number of merge runs we need to perform */
num_runs
=
file
->
offset
;
/* If num_runs are less than 1, nothing to merge */
if
(
num_runs
<=
1
)
{
return
(
error
);
}
/* "run_offset" records each run's first offset number */
run_offset
=
(
ulint
*
)
mem_alloc
(
file
->
offset
*
sizeof
(
ulint
));
/* This tells row_merge() where to start for the first round
of merge. */
run_offset
[
half
]
=
half
;
/* The file should always contain at least one byte (the end
/* The file should always contain at least one byte (the end
of file marker). Thus, it must be at least one block. */
of file marker). Thus, it must be at least one block. */
ut_ad
(
file
->
offset
>
0
);
ut_ad
(
file
->
offset
>
0
);
/* Merge the runs until we have one big run */
do
{
do
{
ulint
error
;
error
=
row_merge
(
trx
,
index
,
file
,
block
,
tmpfd
,
table
,
&
num_runs
,
run_offset
);
error
=
row_merge
(
trx
,
index
,
file
,
&
half
,
UNIV_MEM_ASSERT_RW
(
run_offset
,
num_runs
*
sizeof
*
run_offset
);
block
,
tmpfd
,
table
);
if
(
error
!=
DB_SUCCESS
)
{
if
(
error
!=
DB_SUCCESS
)
{
return
(
error
)
;
break
;
}
}
}
while
(
num_runs
>
1
);
/* half > 0 should hold except when the file consists
mem_free
(
run_offset
);
of one block. No need to merge further then. */
ut_ad
(
half
>
0
||
file
->
offset
==
1
);
}
while
(
half
<
file
->
offset
&&
half
>
0
);
return
(
DB_SUCCESS
);
return
(
error
);
}
}
/*************************************************************//**
/*************************************************************//**
...
@@ -2306,7 +2336,7 @@ row_merge_rename_tables(
...
@@ -2306,7 +2336,7 @@ row_merge_rename_tables(
{
{
ulint
err
=
DB_ERROR
;
ulint
err
=
DB_ERROR
;
pars_info_t
*
info
;
pars_info_t
*
info
;
c
onst
char
*
old_name
=
old_table
->
name
;
c
har
old_name
[
MAX_TABLE_NAME_LEN
+
1
]
;
ut_ad
(
trx
->
mysql_thread_id
==
os_thread_get_curr_id
());
ut_ad
(
trx
->
mysql_thread_id
==
os_thread_get_curr_id
());
ut_ad
(
old_table
!=
new_table
);
ut_ad
(
old_table
!=
new_table
);
...
@@ -2314,6 +2344,17 @@ row_merge_rename_tables(
...
@@ -2314,6 +2344,17 @@ row_merge_rename_tables(
ut_a
(
trx
->
dict_operation_lock_mode
==
RW_X_LATCH
);
ut_a
(
trx
->
dict_operation_lock_mode
==
RW_X_LATCH
);
/* store the old/current name to an automatic variable */
if
(
strlen
(
old_table
->
name
)
+
1
<=
sizeof
(
old_name
))
{
memcpy
(
old_name
,
old_table
->
name
,
strlen
(
old_table
->
name
)
+
1
);
}
else
{
ut_print_timestamp
(
stderr
);
fprintf
(
stderr
,
"InnoDB: too long table name: '%s', "
"max length is %d
\n
"
,
old_table
->
name
,
MAX_TABLE_NAME_LEN
);
ut_error
;
}
trx
->
op_info
=
"renaming tables"
;
trx
->
op_info
=
"renaming tables"
;
/* We use the private SQL parser of Innobase to generate the query
/* We use the private SQL parser of Innobase to generate the query
...
...
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