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
35d4b204
Commit
35d4b204
authored
Nov 16, 2010
by
Mats Kindahl
Browse files
Options
Browse Files
Download
Plain Diff
Merging with mysql-5.5-bugfixing.
parents
6f47ddb9
6131fb34
Changes
31
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
753 additions
and
81 deletions
+753
-81
mysql-test/collections/default.weekly
mysql-test/collections/default.weekly
+1
-1
mysql-test/r/information_schema-big.result
mysql-test/r/information_schema-big.result
+4
-0
mysql-test/r/not_embedded_server.result
mysql-test/r/not_embedded_server.result
+29
-0
mysql-test/r/partition.result
mysql-test/r/partition.result
+33
-0
mysql-test/r/variables-big.result
mysql-test/r/variables-big.result
+5
-5
mysql-test/suite/parts/inc/partition_auto_increment.inc
mysql-test/suite/parts/inc/partition_auto_increment.inc
+49
-0
mysql-test/suite/parts/r/partition_auto_increment_blackhole.result
...t/suite/parts/r/partition_auto_increment_blackhole.result
+32
-0
mysql-test/suite/parts/r/partition_auto_increment_innodb.result
...test/suite/parts/r/partition_auto_increment_innodb.result
+72
-0
mysql-test/suite/parts/r/partition_auto_increment_memory.result
...test/suite/parts/r/partition_auto_increment_memory.result
+72
-0
mysql-test/suite/parts/r/partition_auto_increment_myisam.result
...test/suite/parts/r/partition_auto_increment_myisam.result
+72
-0
mysql-test/t/disabled.def
mysql-test/t/disabled.def
+5
-0
mysql-test/t/not_embedded_server.test
mysql-test/t/not_embedded_server.test
+54
-0
mysql-test/t/partition.test
mysql-test/t/partition.test
+18
-0
mysql-test/t/variables-big.test
mysql-test/t/variables-big.test
+5
-5
mysys/mf_iocache.c
mysys/mf_iocache.c
+24
-24
sql/ha_partition.cc
sql/ha_partition.cc
+93
-6
sql/handler.h
sql/handler.h
+2
-0
sql/log.cc
sql/log.cc
+18
-5
sql/log.h
sql/log.h
+21
-5
sql/mysqld.cc
sql/mysqld.cc
+4
-2
sql/mysqld.h
sql/mysqld.h
+2
-1
sql/sql_class.cc
sql/sql_class.cc
+10
-2
sql/sql_insert.cc
sql/sql_insert.cc
+5
-2
sql/sql_prepare.cc
sql/sql_prepare.cc
+8
-1
sql/sql_update.cc
sql/sql_update.cc
+3
-1
storage/perfschema/pfs_global.h
storage/perfschema/pfs_global.h
+16
-0
storage/perfschema/pfs_instr.cc
storage/perfschema/pfs_instr.cc
+20
-3
storage/perfschema/pfs_instr.h
storage/perfschema/pfs_instr.h
+1
-0
storage/perfschema/pfs_instr_class.cc
storage/perfschema/pfs_instr_class.cc
+58
-12
storage/perfschema/pfs_instr_class.h
storage/perfschema/pfs_instr_class.h
+2
-0
storage/perfschema/table_events_waits.cc
storage/perfschema/table_events_waits.cc
+15
-6
No files found.
mysql-test/collections/default.weekly
View file @
35d4b204
perl mysql-test-run.pl --timer --force --comment=1st --experimental=collections/default.experimental 1st
perl mysql-test-run.pl --timer --force --comment=big-tests --experimental=collections/default.experimental --vardir=var-big-tests --big-test --testcase-timeout=60 --suite-timeout=600
parts.part_supported_sql_func_innodb parts.partition_alter1_1_2_innodb parts.partition_alter1_1_2_ndb parts.partition_alter1_1_ndb parts.partition_alter1_2_innodb parts.partition_alter1_2_ndb parts.partition_alter2_1_1_innodb parts.partition_alter2_1_2_innodb parts.partition_alter2_2_2_innodb parts.partition_alter4_innodb main.variables-big
rpl_ndb.rpl_truncate_7ndb_2
perl mysql-test-run.pl --timer --force --comment=big-tests --experimental=collections/default.experimental --vardir=var-big-tests --big-test --testcase-timeout=60 --suite-timeout=600
large_tests.alter_table main.alter_table-big main.archive-big main.count_distinct3 main.create-big main.events_stress main.events_time_zone main.information_schema-big main.log_tables-big main.merge-big main.mysqlbinlog_row_big main.read_many_rows_innodb main.ssl-big main.sum_distinct-big main.type_newdecimal-big main.variables-big parts.part_supported_sql_func_innodb parts.partition_alter1_1_2_innodb parts.partition_alter1_1_2_ndb parts.partition_alter1_1_ndb parts.partition_alter1_2_innodb parts.partition_alter1_2_ndb parts.partition_alter2_1_1_innodb parts.partition_alter2_1_2_innodb parts.partition_alter2_2_2_innodb parts.partition_alter4_innodb
rpl_ndb.rpl_truncate_7ndb_2
mysql-test/r/information_schema-big.result
View file @
35d4b204
...
...
@@ -30,6 +30,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARAMETERS SPECIFIC_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
PROCESSLIST ID
...
...
@@ -42,6 +43,7 @@ SESSION_STATUS VARIABLE_NAME
SESSION_VARIABLES VARIABLE_NAME
STATISTICS TABLE_SCHEMA
TABLES TABLE_SCHEMA
TABLESPACES TABLESPACE_NAME
TABLE_CONSTRAINTS CONSTRAINT_SCHEMA
TABLE_PRIVILEGES TABLE_SCHEMA
TRIGGERS TRIGGER_SCHEMA
...
...
@@ -74,6 +76,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARAMETERS SPECIFIC_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
PROCESSLIST ID
...
...
@@ -86,6 +89,7 @@ SESSION_STATUS VARIABLE_NAME
SESSION_VARIABLES VARIABLE_NAME
STATISTICS TABLE_SCHEMA
TABLES TABLE_SCHEMA
TABLESPACES TABLESPACE_NAME
TABLE_CONSTRAINTS CONSTRAINT_SCHEMA
TABLE_PRIVILEGES TABLE_SCHEMA
TRIGGERS TRIGGER_SCHEMA
...
...
mysql-test/r/not_embedded_server.result
View file @
35d4b204
...
...
@@ -14,3 +14,32 @@ flush privileges;
ERROR HY000: Table 'host' was not locked with LOCK TABLES
unlock tables;
drop table t1;
#
# Bug#54812: assert in Diagnostics_area::set_ok_status during EXPLAIN
#
CREATE USER nopriv_user@localhost;
connection: default
DROP TABLE IF EXISTS t1,t2,t3;
DROP FUNCTION IF EXISTS f;
CREATE TABLE t1 (key1 INT PRIMARY KEY);
CREATE TABLE t2 (key2 INT);
INSERT INTO t1 VALUES (1),(2);
CREATE FUNCTION f() RETURNS INT RETURN 1;
GRANT FILE ON *.* TO 'nopriv_user'@'localhost';
FLUSH PRIVILEGES;
connection: con1
SELECT MAX(key1) FROM t1 WHERE f() < 1 INTO OUTFILE 'mytest';
ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f'
INSERT INTO t2 SELECT MAX(key1) FROM t1 WHERE f() < 1;
ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f'
SELECT MAX(key1) INTO @dummy FROM t1 WHERE f() < 1;
ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f'
CREATE TABLE t3 (i INT) AS SELECT MAX(key1) FROM t1 WHERE f() < 1;
ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f'
connection: default
DROP TABLE t1,t2;
DROP FUNCTION f;
DROP USER nopriv_user@localhost;
#
# End Bug#54812
#
mysql-test/r/partition.result
View file @
35d4b204
drop table if exists t1, t2;
#
# Bug#57778: failed primary key add to partitioned innodb table
# inconsistent and crashes
#
CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL)
PARTITION BY KEY (a) PARTITIONS 2;
INSERT INTO t1 VALUES (0,1), (0,2);
ALTER TABLE t1 ADD PRIMARY KEY (a);
ERROR 23000: Duplicate entry '0' for key 'PRIMARY'
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY KEY (a)
PARTITIONS 2 */
SELECT * FROM t1;
a b
0 1
0 2
UPDATE t1 SET a = 1, b = 1 WHERE a = 0 AND b = 2;
ALTER TABLE t1 ADD PRIMARY KEY (a);
SELECT * FROM t1;
a b
1 1
0 1
ALTER TABLE t1 DROP PRIMARY KEY;
SELECT * FROM t1;
a b
1 1
0 1
DROP TABLE t1;
#
# Bug#57113: ha_partition::extra(ha_extra_function):
# Assertion `m_extra_cache' failed
CREATE TABLE t1
...
...
mysql-test/r/variables-big.result
View file @
35d4b204
SET SESSION transaction_prealloc_size=1024*1024*1024*1;
SHOW PROCESSLIST;
Id User Host db Command Time State Info
<Id> root
localhost
test Query <Time> NULL SHOW PROCESSLIST
<Id> root
<Host>
test Query <Time> NULL SHOW PROCESSLIST
SET SESSION transaction_prealloc_size=1024*1024*1024*2;
SHOW PROCESSLIST;
Id User Host db Command Time State Info
<Id> root
localhost
test Query <Time> NULL SHOW PROCESSLIST
<Id> root
<Host>
test Query <Time> NULL SHOW PROCESSLIST
SET SESSION transaction_prealloc_size=1024*1024*1024*3;
SHOW PROCESSLIST;
Id User Host db Command Time State Info
<Id> root
localhost
test Query <Time> NULL SHOW PROCESSLIST
<Id> root
<Host>
test Query <Time> NULL SHOW PROCESSLIST
SET SESSION transaction_prealloc_size=1024*1024*1024*4;
SHOW PROCESSLIST;
Id User Host db Command Time State Info
<Id> root
localhost
test Query <Time> NULL SHOW PROCESSLIST
<Id> root
<Host>
test Query <Time> NULL SHOW PROCESSLIST
SET SESSION transaction_prealloc_size=1024*1024*1024*5;
SHOW PROCESSLIST;
Id User Host db Command Time State Info
<Id> root
localhost
test Query <Time> NULL SHOW PROCESSLIST
<Id> root
<Host>
test Query <Time> NULL SHOW PROCESSLIST
mysql-test/suite/parts/inc/partition_auto_increment.inc
View file @
35d4b204
...
...
@@ -105,6 +105,30 @@ OPTIMIZE TABLE t1;
SHOW
CREATE
TABLE
t1
;
DROP
TABLE
t1
;
if
(
!
$skip_update
)
{
eval
CREATE
TABLE
t1
(
a
INT
NULL
AUTO_INCREMENT
,
UNIQUE
KEY
(
a
))
ENGINE
=
$engine
;
SET
LAST_INSERT_ID
=
999
;
SET
INSERT_ID
=
0
;
INSERT
INTO
t1
SET
a
=
1
ON
DUPLICATE
KEY
UPDATE
a
=
NULL
;
SELECT
LAST_INSERT_ID
();
SELECT
*
FROM
t1
;
INSERT
INTO
t1
SET
a
=
1
ON
DUPLICATE
KEY
UPDATE
a
=
NULL
;
SELECT
LAST_INSERT_ID
();
SELECT
*
FROM
t1
;
UPDATE
t1
SET
a
=
1
WHERE
a
IS
NULL
;
SELECT
LAST_INSERT_ID
();
SELECT
*
FROM
t1
;
UPDATE
t1
SET
a
=
NULL
WHERE
a
=
1
;
SELECT
LAST_INSERT_ID
();
SELECT
*
FROM
t1
;
DROP
TABLE
t1
;
SET
INSERT_ID
=
1
;
}
--
echo
# Simple test with NULL
eval
CREATE
TABLE
t1
(
c1
INT
NOT
NULL
AUTO_INCREMENT
,
...
...
@@ -831,5 +855,30 @@ SELECT * FROM t ORDER BY c1 ASC;
DROP
TABLE
t
;
if
(
!
$skip_update
)
{
eval
CREATE
TABLE
t1
(
a
INT
NULL
AUTO_INCREMENT
,
UNIQUE
KEY
(
a
))
ENGINE
=
$engine
PARTITION
BY
KEY
(
a
)
PARTITIONS
2
;
SET
LAST_INSERT_ID
=
999
;
SET
INSERT_ID
=
0
;
INSERT
INTO
t1
SET
a
=
1
ON
DUPLICATE
KEY
UPDATE
a
=
NULL
;
SELECT
LAST_INSERT_ID
();
SELECT
*
FROM
t1
;
INSERT
INTO
t1
SET
a
=
1
ON
DUPLICATE
KEY
UPDATE
a
=
NULL
;
SELECT
LAST_INSERT_ID
();
SELECT
*
FROM
t1
;
UPDATE
t1
SET
a
=
1
WHERE
a
IS
NULL
;
SELECT
LAST_INSERT_ID
();
SELECT
*
FROM
t1
;
UPDATE
t1
SET
a
=
NULL
WHERE
a
=
1
;
SELECT
LAST_INSERT_ID
();
SELECT
*
FROM
t1
;
DROP
TABLE
t1
;
}
--
echo
##############################################################################
}
mysql-test/suite/parts/r/partition_auto_increment_blackhole.result
View file @
35d4b204
...
...
@@ -120,6 +120,38 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`)
) ENGINE=BLACKHOLE DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1
(a INT NULL AUTO_INCREMENT,
UNIQUE KEY (a))
ENGINE='Blackhole';
SET LAST_INSERT_ID = 999;
SET INSERT_ID = 0;
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
UPDATE t1 SET a = 1 WHERE a IS NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
UPDATE t1 SET a = NULL WHERE a = 1;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
DROP TABLE t1;
SET INSERT_ID = 1;
# Simple test with NULL
CREATE TABLE t1 (
c1 INT NOT NULL AUTO_INCREMENT,
...
...
mysql-test/suite/parts/r/partition_auto_increment_innodb.result
View file @
35d4b204
...
...
@@ -136,6 +136,42 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1
(a INT NULL AUTO_INCREMENT,
UNIQUE KEY (a))
ENGINE='InnoDB';
SET LAST_INSERT_ID = 999;
SET INSERT_ID = 0;
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
1
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = 1 WHERE a IS NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = NULL WHERE a = 1;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
DROP TABLE t1;
SET INSERT_ID = 1;
# Simple test with NULL
CREATE TABLE t1 (
c1 INT NOT NULL AUTO_INCREMENT,
...
...
@@ -1023,4 +1059,40 @@ c1 c2
2 20
127 40
DROP TABLE t;
CREATE TABLE t1
(a INT NULL AUTO_INCREMENT,
UNIQUE KEY (a))
ENGINE='InnoDB'
PARTITION BY KEY(a) PARTITIONS 2;
SET LAST_INSERT_ID = 999;
SET INSERT_ID = 0;
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
1
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = 1 WHERE a IS NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = NULL WHERE a = 1;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
DROP TABLE t1;
##############################################################################
mysql-test/suite/parts/r/partition_auto_increment_memory.result
View file @
35d4b204
...
...
@@ -136,6 +136,42 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`)
) ENGINE=MEMORY AUTO_INCREMENT=102 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1
(a INT NULL AUTO_INCREMENT,
UNIQUE KEY (a))
ENGINE='Memory';
SET LAST_INSERT_ID = 999;
SET INSERT_ID = 0;
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
1
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = 1 WHERE a IS NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = NULL WHERE a = 1;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
DROP TABLE t1;
SET INSERT_ID = 1;
# Simple test with NULL
CREATE TABLE t1 (
c1 INT NOT NULL AUTO_INCREMENT,
...
...
@@ -1051,4 +1087,40 @@ c1 c2
2 20
127 40
DROP TABLE t;
CREATE TABLE t1
(a INT NULL AUTO_INCREMENT,
UNIQUE KEY (a))
ENGINE='Memory'
PARTITION BY KEY(a) PARTITIONS 2;
SET LAST_INSERT_ID = 999;
SET INSERT_ID = 0;
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
1
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = 1 WHERE a IS NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = NULL WHERE a = 1;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
DROP TABLE t1;
##############################################################################
mysql-test/suite/parts/r/partition_auto_increment_myisam.result
View file @
35d4b204
...
...
@@ -136,6 +136,42 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`)
) ENGINE=MyISAM AUTO_INCREMENT=102 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1
(a INT NULL AUTO_INCREMENT,
UNIQUE KEY (a))
ENGINE='MyISAM';
SET LAST_INSERT_ID = 999;
SET INSERT_ID = 0;
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
1
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = 1 WHERE a IS NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = NULL WHERE a = 1;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
DROP TABLE t1;
SET INSERT_ID = 1;
# Simple test with NULL
CREATE TABLE t1 (
c1 INT NOT NULL AUTO_INCREMENT,
...
...
@@ -1070,4 +1106,40 @@ c1 c2
2 20
127 40
DROP TABLE t;
CREATE TABLE t1
(a INT NULL AUTO_INCREMENT,
UNIQUE KEY (a))
ENGINE='MyISAM'
PARTITION BY KEY(a) PARTITIONS 2;
SET LAST_INSERT_ID = 999;
SET INSERT_ID = 0;
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
1
INSERT INTO t1 SET a = 1 ON DUPLICATE KEY UPDATE a = NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = 1 WHERE a IS NULL;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
UPDATE t1 SET a = NULL WHERE a = 1;
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
999
SELECT * FROM t1;
a
0
DROP TABLE t1;
##############################################################################
mysql-test/t/disabled.def
View file @
35d4b204
...
...
@@ -15,3 +15,8 @@ query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails spo
ctype_utf8mb4_ndb : Bug#55799, Bug#51907, disabled by Konstantin 2010-08-06
main.mysqlhotcopy_myisam : Bug#56817 2010-10-21 anitha mysqlhotcopy* fails
main.mysqlhotcopy_archive: Bug#56817 2010-10-21 anitha mysqlhotcopy* fails
log_tables-big : Bug#48646 2010-11-15 mattiasj report already exists
read_many_rows_innodb : Bug#37635 2010-11-15 mattiasj report already exists
sum_distinct-big : Bug#56927 2010-11-15 mattiasj was not tested
alter_table-big : Bug#37248 2010-11-15 mattiasj was not tested
create-big : Bug#37248 2010-11-15 mattiasj was not tested
mysql-test/t/not_embedded_server.test
View file @
35d4b204
...
...
@@ -54,3 +54,57 @@ lock tables t1 read;
flush
privileges
;
unlock
tables
;
drop
table
t1
;
--
echo
#
--
echo
# Bug#54812: assert in Diagnostics_area::set_ok_status during EXPLAIN
--
echo
#
CREATE
USER
nopriv_user
@
localhost
;
connection
default
;
--
echo
connection
:
default
--
disable_warnings
DROP
TABLE
IF
EXISTS
t1
,
t2
,
t3
;
DROP
FUNCTION
IF
EXISTS
f
;
--
enable_warnings
CREATE
TABLE
t1
(
key1
INT
PRIMARY
KEY
);
CREATE
TABLE
t2
(
key2
INT
);
INSERT
INTO
t1
VALUES
(
1
),(
2
);
CREATE
FUNCTION
f
()
RETURNS
INT
RETURN
1
;
GRANT
FILE
ON
*.*
TO
'nopriv_user'
@
'localhost'
;
FLUSH
PRIVILEGES
;
connect
(
con1
,
localhost
,
nopriv_user
,,);
connection
con1
;
--
echo
connection
:
con1
--
error
ER_PROCACCESS_DENIED_ERROR
SELECT
MAX
(
key1
)
FROM
t1
WHERE
f
()
<
1
INTO
OUTFILE
'mytest'
;
--
error
ER_PROCACCESS_DENIED_ERROR
INSERT
INTO
t2
SELECT
MAX
(
key1
)
FROM
t1
WHERE
f
()
<
1
;
--
error
ER_PROCACCESS_DENIED_ERROR
SELECT
MAX
(
key1
)
INTO
@
dummy
FROM
t1
WHERE
f
()
<
1
;
--
error
ER_PROCACCESS_DENIED_ERROR
CREATE
TABLE
t3
(
i
INT
)
AS
SELECT
MAX
(
key1
)
FROM
t1
WHERE
f
()
<
1
;
disconnect
con1
;
--
source
include
/
wait_until_disconnected
.
inc
connection
default
;
--
echo
connection
:
default
DROP
TABLE
t1
,
t2
;
DROP
FUNCTION
f
;
DROP
USER
nopriv_user
@
localhost
;
--
echo
#
--
echo
# End Bug#54812
--
echo
#
mysql-test/t/partition.test
View file @
35d4b204
...
...
@@ -14,6 +14,24 @@
drop
table
if
exists
t1
,
t2
;
--
enable_warnings
--
echo
#
--
echo
# Bug#57778: failed primary key add to partitioned innodb table
--
echo
# inconsistent and crashes
--
echo
#
CREATE
TABLE
t1
(
a
INT
NOT
NULL
,
b
INT
NOT
NULL
)
PARTITION
BY
KEY
(
a
)
PARTITIONS
2
;
INSERT
INTO
t1
VALUES
(
0
,
1
),
(
0
,
2
);
--
error
ER_DUP_ENTRY
ALTER
TABLE
t1
ADD
PRIMARY
KEY
(
a
);
SHOW
CREATE
TABLE
t1
;
SELECT
*
FROM
t1
;
UPDATE
t1
SET
a
=
1
,
b
=
1
WHERE
a
=
0
AND
b
=
2
;
ALTER
TABLE
t1
ADD
PRIMARY
KEY
(
a
);
SELECT
*
FROM
t1
;
ALTER
TABLE
t1
DROP
PRIMARY
KEY
;
SELECT
*
FROM
t1
;
DROP
TABLE
t1
;
--
echo
#
--
echo
# Bug#57113: ha_partition::extra(ha_extra_function):
--
echo
# Assertion `m_extra_cache' failed
...
...
mysql-test/t/variables-big.test
View file @
35d4b204
...
...
@@ -37,19 +37,19 @@
--
disable_warnings
SET
SESSION
transaction_prealloc_size
=
1024
*
1024
*
1024
*
1
;
--
replace_column
1
<
Id
>
6
<
Time
>
--
replace_column
1
<
Id
>
3
<
Host
>
6
<
Time
>
SHOW
PROCESSLIST
;
SET
SESSION
transaction_prealloc_size
=
1024
*
1024
*
1024
*
2
;
--
replace_column
1
<
Id
>
6
<
Time
>
--
replace_column
1
<
Id
>
3
<
Host
>
6
<
Time
>
SHOW
PROCESSLIST
;
SET
SESSION
transaction_prealloc_size
=
1024
*
1024
*
1024
*
3
;
--
replace_column
1
<
Id
>
6
<
Time
>
--
replace_column
1
<
Id
>
3
<
Host
>
6
<
Time
>
SHOW
PROCESSLIST
;
SET
SESSION
transaction_prealloc_size
=
1024
*
1024
*
1024
*
4
;
--
replace_column
1
<
Id
>
6
<
Time
>
--
replace_column
1
<
Id
>
3
<
Host
>
6
<
Time
>
SHOW
PROCESSLIST
;
SET
SESSION
transaction_prealloc_size
=
1024
*
1024
*
1024
*
5
;
--
replace_column
1
<
Id
>
6
<
Time
>
--
replace_column
1
<
Id
>
3
<
Host
>
6
<
Time
>
SHOW
PROCESSLIST
;
--
enable_warnings
mysys/mf_iocache.c
View file @
35d4b204
...
...
@@ -173,7 +173,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize,
if
(
file
>=
0
)
{
pos
=
my_tell
(
file
,
MYF
(
0
));
pos
=
my
sql_file
_tell
(
file
,
MYF
(
0
));
if
((
pos
==
(
my_off_t
)
-
1
)
&&
(
my_errno
==
ESPIPE
))
{
/*
...
...
@@ -205,7 +205,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize,
if
(
!
(
cache_myflags
&
MY_DONT_CHECK_FILESIZE
))
{
/* Calculate end of file to avoid allocating oversized buffers */
end_of_file
=
my_seek
(
file
,
0L
,
MY_SEEK_END
,
MYF
(
0
));
end_of_file
=
mysql_file_seek
(
file
,
0L
,
MY_SEEK_END
,
MYF
(
0
));
/* Need to reset seek_not_done now that we just did a seek. */
info
->
seek_not_done
=
end_of_file
==
seek_offset
?
0
:
1
;
if
(
end_of_file
<
seek_offset
)
...
...
@@ -485,7 +485,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
*/
if
(
info
->
seek_not_done
)
{
if
((
my
_seek
(
info
->
file
,
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
if
((
my
sql_file_seek
(
info
->
file
,
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
!=
MY_FILEPOS_ERROR
))
{
/* No error, reset seek_not_done flag. */
...
...
@@ -529,7 +529,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
end aligned with a block.
*/
length
=
(
Count
&
(
size_t
)
~
(
IO_SIZE
-
1
))
-
diff_length
;
if
((
read_length
=
my_read
(
info
->
file
,
Buffer
,
length
,
info
->
myflags
))
if
((
read_length
=
my
sql_file
_read
(
info
->
file
,
Buffer
,
length
,
info
->
myflags
))
!=
length
)
{
/*
...
...
@@ -572,7 +572,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
}
length
=
0
;
/* Didn't read any chars */
}
else
if
((
length
=
my_read
(
info
->
file
,
info
->
buffer
,
max_length
,
else
if
((
length
=
my
sql_file
_read
(
info
->
file
,
info
->
buffer
,
max_length
,
info
->
myflags
))
<
Count
||
length
==
(
size_t
)
-
1
)
{
...
...
@@ -1056,7 +1056,7 @@ int _my_b_read_r(register IO_CACHE *cache, uchar *Buffer, size_t Count)
*/
if
(
cache
->
seek_not_done
)
{
if
(
my_seek
(
cache
->
file
,
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
if
(
my
sql_file
_seek
(
cache
->
file
,
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
==
MY_FILEPOS_ERROR
)
{
cache
->
error
=
-
1
;
...
...
@@ -1064,7 +1064,7 @@ int _my_b_read_r(register IO_CACHE *cache, uchar *Buffer, size_t Count)
DBUG_RETURN
(
1
);
}
}
len
=
my_read
(
cache
->
file
,
cache
->
buffer
,
length
,
cache
->
myflags
);
len
=
my
sql_file
_read
(
cache
->
file
,
cache
->
buffer
,
length
,
cache
->
myflags
);
}
DBUG_PRINT
(
"io_cache_share"
,
(
"read %lu bytes"
,
(
ulong
)
len
));
...
...
@@ -1203,7 +1203,7 @@ int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
With read-append cache we must always do a seek before we read,
because the write could have moved the file pointer astray
*/
if
(
my
_seek
(
info
->
file
,
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
==
MY_FILEPOS_ERROR
)
if
(
my
sql_file_seek
(
info
->
file
,
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
==
MY_FILEPOS_ERROR
)
{
info
->
error
=
-
1
;
unlock_append_buffer
(
info
);
...
...
@@ -1220,8 +1220,8 @@ int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
size_t
read_length
;
length
=
(
Count
&
(
size_t
)
~
(
IO_SIZE
-
1
))
-
diff_length
;
if
((
read_length
=
my_read
(
info
->
file
,
Buffer
,
length
,
info
->
myflags
))
==
(
size_t
)
-
1
)
if
((
read_length
=
my
sql_file
_read
(
info
->
file
,
Buffer
,
length
,
info
->
myflags
))
==
(
size_t
)
-
1
)
{
info
->
error
=
-
1
;
unlock_append_buffer
(
info
);
...
...
@@ -1254,7 +1254,7 @@ int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
}
else
{
length
=
my_read
(
info
->
file
,
info
->
buffer
,
max_length
,
info
->
myflags
);
length
=
my
sql_file
_read
(
info
->
file
,
info
->
buffer
,
max_length
,
info
->
myflags
);
if
(
length
==
(
size_t
)
-
1
)
{
info
->
error
=
-
1
;
...
...
@@ -1431,7 +1431,7 @@ int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
return
1
;
}
if
(
my
_seek
(
info
->
file
,
next_pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
if
(
my
sql_file_seek
(
info
->
file
,
next_pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
==
MY_FILEPOS_ERROR
)
{
info
->
error
=
-
1
;
...
...
@@ -1441,8 +1441,8 @@ int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
read_length
=
IO_SIZE
*
2
-
(
size_t
)
(
next_pos_in_file
&
(
IO_SIZE
-
1
));
if
(
Count
<
read_length
)
{
/* Small block, read to cache */
if
((
read_length
=
my_read
(
info
->
file
,
info
->
request_pos
,
read_length
,
info
->
myflags
))
==
(
size_t
)
-
1
)
if
((
read_length
=
my
sql_file
_read
(
info
->
file
,
info
->
request_pos
,
read_length
,
info
->
myflags
))
==
(
size_t
)
-
1
)
return
info
->
error
=
-
1
;
use_length
=
min
(
Count
,
read_length
);
memcpy
(
Buffer
,
info
->
request_pos
,(
size_t
)
use_length
);
...
...
@@ -1462,7 +1462,7 @@ int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
}
else
{
/* Big block, don't cache it */
if
((
read_length
=
my
_read
(
info
->
file
,
Buffer
,
Count
,
info
->
myflags
))
if
((
read_length
=
my
sql_file_read
(
info
->
file
,
Buffer
,
Count
,
info
->
myflags
))
!=
Count
)
{
info
->
error
=
read_length
==
(
size_t
)
-
1
?
-
1
:
read_length
+
left_length
;
...
...
@@ -1569,14 +1569,14 @@ int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count)
"seek_not_done" to indicate this to other functions operating
on the IO_CACHE.
*/
if
(
my
_seek
(
info
->
file
,
info
->
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
)))
if
(
my
sql_file_seek
(
info
->
file
,
info
->
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
)))
{
info
->
error
=
-
1
;
return
(
1
);
}
info
->
seek_not_done
=
0
;
}
if
(
my_write
(
info
->
file
,
Buffer
,
length
,
info
->
myflags
|
MY_NABP
))
if
(
my
sql_file
_write
(
info
->
file
,
Buffer
,
length
,
info
->
myflags
|
MY_NABP
))
return
info
->
error
=
-
1
;
#ifdef THREAD
...
...
@@ -1639,7 +1639,7 @@ int my_b_append(register IO_CACHE *info, const uchar *Buffer, size_t Count)
if
(
Count
>=
IO_SIZE
)
{
/* Fill first intern buffer */
length
=
Count
&
(
size_t
)
~
(
IO_SIZE
-
1
);
if
(
my_write
(
info
->
file
,
Buffer
,
length
,
info
->
myflags
|
MY_NABP
))
if
(
my
sql_file
_write
(
info
->
file
,
Buffer
,
length
,
info
->
myflags
|
MY_NABP
))
{
unlock_append_buffer
(
info
);
return
info
->
error
=
-
1
;
...
...
@@ -1695,11 +1695,11 @@ int my_block_write(register IO_CACHE *info, const uchar *Buffer, size_t Count,
{
/* Of no overlap, write everything without buffering */
if
(
pos
+
Count
<=
info
->
pos_in_file
)
return
my_pwrite
(
info
->
file
,
Buffer
,
Count
,
pos
,
info
->
myflags
|
MY_NABP
);
return
my
sql_file
_pwrite
(
info
->
file
,
Buffer
,
Count
,
pos
,
info
->
myflags
|
MY_NABP
);
/* Write the part of the block that is before buffer */
length
=
(
uint
)
(
info
->
pos_in_file
-
pos
);
if
(
my_pwrite
(
info
->
file
,
Buffer
,
length
,
pos
,
info
->
myflags
|
MY_NABP
))
if
(
my
sql_file
_pwrite
(
info
->
file
,
Buffer
,
length
,
pos
,
info
->
myflags
|
MY_NABP
))
info
->
error
=
error
=
-
1
;
Buffer
+=
length
;
pos
+=
length
;
...
...
@@ -1789,7 +1789,7 @@ int my_b_flush_io_cache(IO_CACHE *info,
*/
if
(
!
append_cache
&&
info
->
seek_not_done
)
{
/* File touched, do seek */
if
(
my
_seek
(
info
->
file
,
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
==
if
(
my
sql_file_seek
(
info
->
file
,
pos_in_file
,
MY_SEEK_SET
,
MYF
(
0
))
==
MY_FILEPOS_ERROR
)
{
UNLOCK_APPEND_BUFFER
;
...
...
@@ -1803,7 +1803,7 @@ int my_b_flush_io_cache(IO_CACHE *info,
info
->
write_end
=
(
info
->
write_buffer
+
info
->
buffer_length
-
((
pos_in_file
+
length
)
&
(
IO_SIZE
-
1
)));
if
(
my_write
(
info
->
file
,
info
->
write_buffer
,
length
,
if
(
my
sql_file
_write
(
info
->
file
,
info
->
write_buffer
,
length
,
info
->
myflags
|
MY_NABP
))
info
->
error
=
-
1
;
else
...
...
@@ -1815,7 +1815,7 @@ int my_b_flush_io_cache(IO_CACHE *info,
else
{
info
->
end_of_file
+=
(
info
->
write_pos
-
info
->
append_read_pos
);
DBUG_ASSERT
(
info
->
end_of_file
==
my
_tell
(
info
->
file
,
MYF
(
0
)));
DBUG_ASSERT
(
info
->
end_of_file
==
my
sql_file_tell
(
info
->
file
,
MYF
(
0
)));
}
info
->
append_read_pos
=
info
->
write_pos
=
info
->
write_buffer
;
...
...
sql/ha_partition.cc
View file @
35d4b204
...
...
@@ -3093,7 +3093,9 @@ int ha_partition::write_row(uchar * buf)
bool
have_auto_increment
=
table
->
next_number_field
&&
buf
==
table
->
record
[
0
];
my_bitmap_map
*
old_map
;
THD
*
thd
=
ha_thd
();
timestamp_auto_set_type
orig_timestamp_type
=
table
->
timestamp_field_type
;
timestamp_auto_set_type
saved_timestamp_type
=
table
->
timestamp_field_type
;
ulong
saved_sql_mode
=
thd
->
variables
.
sql_mode
;
bool
saved_auto_inc_field_not_null
=
table
->
auto_increment_field_not_null
;
#ifdef NOT_NEEDED
uchar
*
rec0
=
m_rec0
;
#endif
...
...
@@ -3129,6 +3131,22 @@ int ha_partition::write_row(uchar * buf)
*/
if
(
error
)
goto
exit
;
/*
Don't allow generation of auto_increment value the partitions handler.
If a partitions handler would change the value, then it might not
match the partition any longer.
This can occur if 'SET INSERT_ID = 0; INSERT (NULL)',
So allow this by adding 'MODE_NO_AUTO_VALUE_ON_ZERO' to sql_mode.
The partitions handler::next_insert_id must always be 0. Otherwise
we need to forward release_auto_increment, or reset it for all
partitions.
*/
if
(
table
->
next_number_field
->
val_int
()
==
0
)
{
table
->
auto_increment_field_not_null
=
TRUE
;
thd
->
variables
.
sql_mode
|=
MODE_NO_AUTO_VALUE_ON_ZERO
;
}
}
old_map
=
dbug_tmp_use_all_columns
(
table
,
table
->
read_set
);
...
...
@@ -3162,7 +3180,9 @@ int ha_partition::write_row(uchar * buf)
set_auto_increment_if_higher
(
table
->
next_number_field
);
reenable_binlog
(
thd
);
exit:
table
->
timestamp_field_type
=
orig_timestamp_type
;
thd
->
variables
.
sql_mode
=
saved_sql_mode
;
table
->
auto_increment_field_not_null
=
saved_auto_inc_field_not_null
;
table
->
timestamp_field_type
=
saved_timestamp_type
;
DBUG_RETURN
(
error
);
}
...
...
@@ -3229,11 +3249,24 @@ int ha_partition::update_row(const uchar *old_data, uchar *new_data)
}
else
{
Field
*
saved_next_number_field
=
table
->
next_number_field
;
/*
Don't allow generation of auto_increment value for update.
table->next_number_field is never set on UPDATE.
But is set for INSERT ... ON DUPLICATE KEY UPDATE,
and since update_row() does not generate or update an auto_inc value,
we cannot have next_number_field set when moving a row
to another partition with write_row(), since that could
generate/update the auto_inc value.
This gives the same behavior for partitioned vs non partitioned tables.
*/
table
->
next_number_field
=
NULL
;
DBUG_PRINT
(
"info"
,
(
"Update from partition %d to partition %d"
,
old_part_id
,
new_part_id
));
tmp_disable_binlog
(
thd
);
/* Do not replicate the low-level changes. */
error
=
m_file
[
new_part_id
]
->
ha_write_row
(
new_data
);
reenable_binlog
(
thd
);
table
->
next_number_field
=
saved_next_number_field
;
if
(
error
)
goto
exit
;
...
...
@@ -6375,9 +6408,42 @@ bool ha_partition::get_error_message(int error, String *buf)
*/
uint
ha_partition
::
alter_table_flags
(
uint
flags
)
{
uint
flags_to_return
,
flags_to_check
;
DBUG_ENTER
(
"ha_partition::alter_table_flags"
);
DBUG_RETURN
(
ht
->
alter_table_flags
(
flags
)
|
m_file
[
0
]
->
alter_table_flags
(
flags
));
flags_to_return
=
ht
->
alter_table_flags
(
flags
);
flags_to_return
|=
m_file
[
0
]
->
alter_table_flags
(
flags
);
/*
If one partition fails we must be able to revert the change for the other,
already altered, partitions. So both ADD and DROP can only be supported in
pairs.
*/
flags_to_check
=
HA_ONLINE_ADD_INDEX_NO_WRITES
;
flags_to_check
|=
HA_ONLINE_DROP_INDEX_NO_WRITES
;
if
((
flags_to_return
&
flags_to_check
)
!=
flags_to_check
)
flags_to_return
&=
~
flags_to_check
;
flags_to_check
=
HA_ONLINE_ADD_UNIQUE_INDEX_NO_WRITES
;
flags_to_check
|=
HA_ONLINE_DROP_UNIQUE_INDEX_NO_WRITES
;
if
((
flags_to_return
&
flags_to_check
)
!=
flags_to_check
)
flags_to_return
&=
~
flags_to_check
;
flags_to_check
=
HA_ONLINE_ADD_PK_INDEX_NO_WRITES
;
flags_to_check
|=
HA_ONLINE_DROP_PK_INDEX_NO_WRITES
;
if
((
flags_to_return
&
flags_to_check
)
!=
flags_to_check
)
flags_to_return
&=
~
flags_to_check
;
flags_to_check
=
HA_ONLINE_ADD_INDEX
;
flags_to_check
|=
HA_ONLINE_DROP_INDEX
;
if
((
flags_to_return
&
flags_to_check
)
!=
flags_to_check
)
flags_to_return
&=
~
flags_to_check
;
flags_to_check
=
HA_ONLINE_ADD_UNIQUE_INDEX
;
flags_to_check
|=
HA_ONLINE_DROP_UNIQUE_INDEX
;
if
((
flags_to_return
&
flags_to_check
)
!=
flags_to_check
)
flags_to_return
&=
~
flags_to_check
;
flags_to_check
=
HA_ONLINE_ADD_PK_INDEX
;
flags_to_check
|=
HA_ONLINE_DROP_PK_INDEX
;
if
((
flags_to_return
&
flags_to_check
)
!=
flags_to_check
)
flags_to_return
&=
~
flags_to_check
;
DBUG_RETURN
(
flags_to_return
);
}
...
...
@@ -6412,6 +6478,7 @@ int ha_partition::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
handler
**
file
;
int
ret
=
0
;
DBUG_ENTER
(
"ha_partition::add_index"
);
/*
There has already been a check in fix_partition_func in mysql_alter_table
before this call, which checks for unique/primary key violations of the
...
...
@@ -6419,8 +6486,28 @@ int ha_partition::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
*/
for
(
file
=
m_file
;
*
file
;
file
++
)
if
((
ret
=
(
*
file
)
->
add_index
(
table_arg
,
key_info
,
num_of_keys
)))
break
;
return
ret
;
goto
err
;
DBUG_RETURN
(
ret
);
err:
if
(
file
>
m_file
)
{
uint
*
key_numbers
=
(
uint
*
)
ha_thd
()
->
alloc
(
sizeof
(
uint
)
*
num_of_keys
);
uint
old_num_of_keys
=
table_arg
->
s
->
keys
;
uint
i
;
/* The newly created keys have the last id's */
for
(
i
=
0
;
i
<
num_of_keys
;
i
++
)
key_numbers
[
i
]
=
i
+
old_num_of_keys
;
if
(
!
table_arg
->
key_info
)
table_arg
->
key_info
=
key_info
;
while
(
--
file
>=
m_file
)
{
(
void
)
(
*
file
)
->
prepare_drop_index
(
table_arg
,
key_numbers
,
num_of_keys
);
(
void
)
(
*
file
)
->
final_drop_index
(
table_arg
);
}
if
(
table_arg
->
key_info
==
key_info
)
table_arg
->
key_info
=
NULL
;
}
DBUG_RETURN
(
ret
);
}
...
...
sql/handler.h
View file @
35d4b204
...
...
@@ -174,6 +174,8 @@
/*
These bits are set if different kinds of indexes can be created
off-line without re-create of the table (but with a table lock).
Partitioning needs both ADD and DROP to be supported by its underlying
handlers, due to error handling, see bug#57778.
*/
#define HA_ONLINE_ADD_INDEX_NO_WRITES (1L << 0)
/*add index w/lock*/
#define HA_ONLINE_DROP_INDEX_NO_WRITES (1L << 1)
/*drop index w/lock*/
...
...
sql/log.cc
View file @
35d4b204
...
...
@@ -2177,7 +2177,11 @@ bool MYSQL_LOG::init_and_set_log_file_name(const char *log_name,
1 error
*/
bool
MYSQL_LOG
::
open
(
const
char
*
log_name
,
enum_log_type
log_type_arg
,
bool
MYSQL_LOG
::
open
(
#ifdef HAVE_PSI_INTERFACE
PSI_file_key
log_file_key
,
#endif
const
char
*
log_name
,
enum_log_type
log_type_arg
,
const
char
*
new_name
,
enum
cache_type
io_cache_type_arg
)
{
char
buff
[
FN_REFLEN
];
...
...
@@ -2205,7 +2209,12 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
db
[
0
]
=
0
;
if
((
file
=
mysql_file_open
(
key_file_MYSQL_LOG
,
#ifdef HAVE_PSI_INTERFACE
/* Keep the key for reopen */
m_log_file_key
=
log_file_key
;
#endif
if
((
file
=
mysql_file_open
(
log_file_key
,
log_file_name
,
open_flags
,
MYF
(
MY_WME
|
ME_WAITTANG
)))
<
0
||
init_io_cache
(
&
log_file
,
file
,
IO_SIZE
,
io_cache_type
,
...
...
@@ -2389,7 +2398,11 @@ void MYSQL_QUERY_LOG::reopen_file()
Note that at this point, log_state != LOG_CLOSED (important for is_open()).
*/
open
(
save_name
,
log_type
,
0
,
io_cache_type
);
open
(
#ifdef HAVE_PSI_INTERFACE
m_log_file_key
,
#endif
save_name
,
log_type
,
0
,
io_cache_type
);
my_free
(
save_name
);
mysql_mutex_unlock
(
&
LOCK_log
);
...
...
@@ -2855,8 +2868,8 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
write_error
=
0
;
/* open the main log file */
if
(
MYSQL_LOG
::
open
(
log_name
,
log_type_arg
,
new_name
,
io_cache_type_arg
))
if
(
MYSQL_LOG
::
open
(
key_file_binlog
,
log_name
,
log_type_arg
,
new_name
,
io_cache_type_arg
))
{
#ifdef HAVE_REPLICATION
close_purge_index_file
();
...
...
sql/log.h
View file @
35d4b204
...
...
@@ -196,7 +196,11 @@ class MYSQL_LOG
MYSQL_LOG
();
void
init_pthread_objects
();
void
cleanup
();
bool
open
(
const
char
*
log_name
,
bool
open
(
#ifdef HAVE_PSI_INTERFACE
PSI_file_key
log_file_key
,
#endif
const
char
*
log_name
,
enum_log_type
log_type
,
const
char
*
new_name
,
enum
cache_type
io_cache_type_arg
);
...
...
@@ -223,6 +227,10 @@ class MYSQL_LOG
volatile
enum_log_state
log_state
;
enum
cache_type
io_cache_type
;
friend
class
Log_event
;
#ifdef HAVE_PSI_INTERFACE
/** Instrumentation key to use for file io in @c log_file */
PSI_file_key
m_log_file_key
;
#endif
};
class
MYSQL_QUERY_LOG
:
public
MYSQL_LOG
...
...
@@ -241,14 +249,22 @@ class MYSQL_QUERY_LOG: public MYSQL_LOG
bool
open_slow_log
(
const
char
*
log_name
)
{
char
buf
[
FN_REFLEN
];
return
open
(
generate_name
(
log_name
,
"-slow.log"
,
0
,
buf
),
LOG_NORMAL
,
0
,
WRITE_CACHE
);
return
open
(
#ifdef HAVE_PSI_INTERFACE
key_file_slow_log
,
#endif
generate_name
(
log_name
,
"-slow.log"
,
0
,
buf
),
LOG_NORMAL
,
0
,
WRITE_CACHE
);
}
bool
open_query_log
(
const
char
*
log_name
)
{
char
buf
[
FN_REFLEN
];
return
open
(
generate_name
(
log_name
,
".log"
,
0
,
buf
),
LOG_NORMAL
,
0
,
WRITE_CACHE
);
return
open
(
#ifdef HAVE_PSI_INTERFACE
key_file_query_log
,
#endif
generate_name
(
log_name
,
".log"
,
0
,
buf
),
LOG_NORMAL
,
0
,
WRITE_CACHE
);
}
private:
...
...
sql/mysqld.cc
View file @
35d4b204
...
...
@@ -7838,9 +7838,10 @@ PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest,
key_file_dbopt
,
key_file_des_key_file
,
key_file_ERRMSG
,
key_select_to_file
,
key_file_fileparser
,
key_file_frm
,
key_file_global_ddl_log
,
key_file_load
,
key_file_loadfile
,
key_file_log_event_data
,
key_file_log_event_info
,
key_file_master_info
,
key_file_misc
,
key_file_
MYSQL_LOG
,
key_file_
partition
,
key_file_master_info
,
key_file_misc
,
key_file_partition
,
key_file_pid
,
key_file_relay_log_info
,
key_file_send_file
,
key_file_tclog
,
key_file_trg
,
key_file_trn
,
key_file_init
;
PSI_file_key
key_file_query_log
,
key_file_slow_log
;
static
PSI_file_info
all_server_files
[]
=
{
...
...
@@ -7863,11 +7864,12 @@ static PSI_file_info all_server_files[]=
{
&
key_file_log_event_info
,
"log_event_info"
,
0
},
{
&
key_file_master_info
,
"master_info"
,
0
},
{
&
key_file_misc
,
"misc"
,
0
},
{
&
key_file_MYSQL_LOG
,
"MYSQL_LOG"
,
0
},
{
&
key_file_partition
,
"partition"
,
0
},
{
&
key_file_pid
,
"pid"
,
0
},
{
&
key_file_query_log
,
"query_log"
,
0
},
{
&
key_file_relay_log_info
,
"relay_log_info"
,
0
},
{
&
key_file_send_file
,
"send_file"
,
0
},
{
&
key_file_slow_log
,
"slow_log"
,
0
},
{
&
key_file_tclog
,
"tclog"
,
0
},
{
&
key_file_trg
,
"trigger_name"
,
0
},
{
&
key_file_trn
,
"trigger"
,
0
},
...
...
sql/mysqld.h
View file @
35d4b204
...
...
@@ -270,9 +270,10 @@ extern PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest,
key_file_dbopt
,
key_file_des_key_file
,
key_file_ERRMSG
,
key_select_to_file
,
key_file_fileparser
,
key_file_frm
,
key_file_global_ddl_log
,
key_file_load
,
key_file_loadfile
,
key_file_log_event_data
,
key_file_log_event_info
,
key_file_master_info
,
key_file_misc
,
key_file_
MYSQL_LOG
,
key_file_
partition
,
key_file_master_info
,
key_file_misc
,
key_file_partition
,
key_file_pid
,
key_file_relay_log_info
,
key_file_send_file
,
key_file_tclog
,
key_file_trg
,
key_file_trn
,
key_file_init
;
extern
PSI_file_key
key_file_query_log
,
key_file_slow_log
;
void
init_server_psi_keys
();
#endif
/* HAVE_PSI_INTERFACE */
...
...
sql/sql_class.cc
View file @
35d4b204
...
...
@@ -1842,8 +1842,9 @@ void select_to_file::send_error(uint errcode,const char *err)
bool
select_to_file
::
send_eof
()
{
int
error
=
test
(
end_io_cache
(
&
cache
));
if
(
mysql_file_close
(
file
,
MYF
(
MY_WME
)))
error
=
1
;
if
(
mysql_file_close
(
file
,
MYF
(
MY_WME
))
||
thd
->
is_error
())
error
=
true
;
if
(
!
error
)
{
::
my_ok
(
thd
,
row_count
);
...
...
@@ -2884,6 +2885,13 @@ bool select_dumpvar::send_eof()
if
(
!
row_count
)
push_warning
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_SP_FETCH_NO_DATA
,
ER
(
ER_SP_FETCH_NO_DATA
));
/*
Don't send EOF if we're in error condition (which implies we've already
sent or are sending an error)
*/
if
(
thd
->
is_error
())
return
true
;
::
my_ok
(
thd
,
row_count
);
return
0
;
}
...
...
sql/sql_insert.cc
View file @
35d4b204
...
...
@@ -3506,6 +3506,9 @@ bool select_insert::send_eof()
error
=
(
thd
->
locked_tables_mode
<=
LTM_LOCK_TABLES
?
table
->
file
->
ha_end_bulk_insert
()
:
0
);
if
(
!
error
&&
thd
->
is_error
())
error
=
thd
->
stmt_da
->
sql_errno
();
table
->
file
->
extra
(
HA_EXTRA_NO_IGNORE_DUP_KEY
);
table
->
file
->
extra
(
HA_EXTRA_WRITE_CANNOT_REPLACE
);
...
...
@@ -4049,7 +4052,7 @@ bool select_create::send_eof()
{
bool
tmp
=
select_insert
::
send_eof
();
if
(
tmp
)
abort
();
abort
_result_set
();
else
{
/*
...
...
@@ -4081,7 +4084,7 @@ void select_create::abort_result_set()
DBUG_ENTER
(
"select_create::abort_result_set"
);
/*
In select_insert::abort() we roll back the statement, including
In select_insert::abort
_result_set
() we roll back the statement, including
truncating the transaction cache of the binary log. To do this, we
pretend that the statement is transactional, even though it might
be the case that it was not.
...
...
sql/sql_prepare.cc
View file @
35d4b204
...
...
@@ -2898,8 +2898,15 @@ bool Select_fetch_protocol_binary::send_result_set_metadata(List<Item> &list, ui
bool
Select_fetch_protocol_binary
::
send_eof
()
{
/*
Don't send EOF if we're in error condition (which implies we've already
sent or are sending an error)
*/
if
(
thd
->
is_error
())
return
true
;
::
my_eof
(
thd
);
return
FALSE
;
return
false
;
}
...
...
sql/sql_update.cc
View file @
35d4b204
...
...
@@ -2064,7 +2064,9 @@ bool multi_update::send_eof()
Does updates for the last n - 1 tables, returns 0 if ok;
error takes into account killed status gained in do_updates()
*/
int
local_error
=
(
table_count
)
?
do_updates
()
:
0
;
int
local_error
=
thd
->
is_error
();
if
(
!
local_error
)
local_error
=
(
table_count
)
?
do_updates
()
:
0
;
/*
if local_error is not set ON until after do_updates() then
later carried out killing should not affect binlogging.
...
...
storage/perfschema/pfs_global.h
View file @
35d4b204
...
...
@@ -79,5 +79,21 @@ inline uint randomized_index(const void *ptr, uint max_size)
void
pfs_print_error
(
const
char
*
format
,
...);
/**
Given an array defined as T ARRAY[MAX],
check that an UNSAFE pointer actually points to an element
within the array.
*/
#define SANITIZE_ARRAY_BODY(T, ARRAY, MAX, UNSAFE) \
intptr offset; \
if ((&ARRAY[0] <= UNSAFE) && \
(UNSAFE < &ARRAY[MAX])) \
{ \
offset= ((intptr) UNSAFE - (intptr) ARRAY) % sizeof(T); \
if (offset == 0) \
return UNSAFE; \
} \
return NULL
#endif
storage/perfschema/pfs_instr.cc
View file @
35d4b204
...
...
@@ -758,9 +758,26 @@ PFS_thread* create_thread(PFS_thread_class *klass, const void *identity,
*/
PFS_thread
*
sanitize_thread
(
PFS_thread
*
unsafe
)
{
if
((
&
thread_array
[
0
]
<=
unsafe
)
&&
(
unsafe
<
&
thread_array
[
thread_max
]))
return
unsafe
;
SANITIZE_ARRAY_BODY
(
PFS_thread
,
thread_array
,
thread_max
,
unsafe
);
}
const
char
*
sanitize_file_name
(
const
char
*
unsafe
)
{
intptr
ptr
=
(
intptr
)
unsafe
;
intptr
first
=
(
intptr
)
&
file_array
[
0
];
intptr
last
=
(
intptr
)
&
file_array
[
file_max
];
/* Check if unsafe points inside file_array[] */
if
(
likely
((
first
<=
ptr
)
&&
(
ptr
<
last
)))
{
/* Check if unsafe points to PFS_file::m_filename */
intptr
offset
=
(
ptr
-
first
)
%
sizeof
(
PFS_file
);
intptr
valid_offset
=
my_offsetof
(
PFS_file
,
m_filename
[
0
]);
if
(
likely
(
offset
==
valid_offset
))
{
return
unsafe
;
}
}
return
NULL
;
}
...
...
storage/perfschema/pfs_instr.h
View file @
35d4b204
...
...
@@ -227,6 +227,7 @@ struct PFS_thread
};
PFS_thread
*
sanitize_thread
(
PFS_thread
*
unsafe
);
const
char
*
sanitize_file_name
(
const
char
*
unsafe
);
PFS_single_stat_chain
*
find_per_thread_mutex_class_wait_stat
(
PFS_thread
*
thread
,
...
...
storage/perfschema/pfs_instr_class.cc
View file @
35d4b204
...
...
@@ -543,15 +543,9 @@ PFS_mutex_class *find_mutex_class(PFS_sync_key key)
FIND_CLASS_BODY
(
key
,
mutex_class_allocated_count
,
mutex_class_array
);
}
#define SANITIZE_ARRAY_BODY(ARRAY, MAX, UNSAFE) \
if ((&ARRAY[0] <= UNSAFE) && \
(UNSAFE < &ARRAY[MAX])) \
return UNSAFE; \
return NULL
PFS_mutex_class
*
sanitize_mutex_class
(
PFS_mutex_class
*
unsafe
)
{
SANITIZE_ARRAY_BODY
(
mutex_class_array
,
mutex_class_max
,
unsafe
);
SANITIZE_ARRAY_BODY
(
PFS_mutex_class
,
mutex_class_array
,
mutex_class_max
,
unsafe
);
}
/**
...
...
@@ -566,7 +560,7 @@ PFS_rwlock_class *find_rwlock_class(PFS_sync_key key)
PFS_rwlock_class
*
sanitize_rwlock_class
(
PFS_rwlock_class
*
unsafe
)
{
SANITIZE_ARRAY_BODY
(
rwlock_class_array
,
rwlock_class_max
,
unsafe
);
SANITIZE_ARRAY_BODY
(
PFS_rwlock_class
,
rwlock_class_array
,
rwlock_class_max
,
unsafe
);
}
/**
...
...
@@ -581,7 +575,7 @@ PFS_cond_class *find_cond_class(PFS_sync_key key)
PFS_cond_class
*
sanitize_cond_class
(
PFS_cond_class
*
unsafe
)
{
SANITIZE_ARRAY_BODY
(
cond_class_array
,
cond_class_max
,
unsafe
);
SANITIZE_ARRAY_BODY
(
PFS_cond_class
,
cond_class_array
,
cond_class_max
,
unsafe
);
}
/**
...
...
@@ -636,7 +630,7 @@ PFS_thread_class *find_thread_class(PFS_sync_key key)
PFS_thread_class
*
sanitize_thread_class
(
PFS_thread_class
*
unsafe
)
{
SANITIZE_ARRAY_BODY
(
thread_class_array
,
thread_class_max
,
unsafe
);
SANITIZE_ARRAY_BODY
(
PFS_thread_class
,
thread_class_array
,
thread_class_max
,
unsafe
);
}
/**
...
...
@@ -687,7 +681,7 @@ PFS_file_class *find_file_class(PFS_file_key key)
PFS_file_class
*
sanitize_file_class
(
PFS_file_class
*
unsafe
)
{
SANITIZE_ARRAY_BODY
(
file_class_array
,
file_class_max
,
unsafe
);
SANITIZE_ARRAY_BODY
(
PFS_file_class
,
file_class_array
,
file_class_max
,
unsafe
);
}
/**
...
...
@@ -820,7 +814,59 @@ PFS_table_share* find_or_create_table_share(PFS_thread *thread,
PFS_table_share
*
sanitize_table_share
(
PFS_table_share
*
unsafe
)
{
SANITIZE_ARRAY_BODY
(
table_share_array
,
table_share_max
,
unsafe
);
SANITIZE_ARRAY_BODY
(
PFS_table_share
,
table_share_array
,
table_share_max
,
unsafe
);
}
const
char
*
sanitize_table_schema_name
(
const
char
*
unsafe
)
{
intptr
ptr
=
(
intptr
)
unsafe
;
intptr
first
=
(
intptr
)
&
table_share_array
[
0
];
intptr
last
=
(
intptr
)
&
table_share_array
[
table_share_max
];
PFS_table_share
dummy
;
/* Check if unsafe points inside table_share_array[] */
if
(
likely
((
first
<=
ptr
)
&&
(
ptr
<
last
)))
{
intptr
offset
=
(
ptr
-
first
)
%
sizeof
(
PFS_table_share
);
intptr
from
=
my_offsetof
(
PFS_table_share
,
m_key
.
m_hash_key
);
intptr
len
=
sizeof
(
dummy
.
m_key
.
m_hash_key
);
/* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */
if
(
likely
((
from
<=
offset
)
&&
(
offset
<
from
+
len
)))
{
PFS_table_share
*
base
=
(
PFS_table_share
*
)
(
ptr
-
offset
);
/* Check if unsafe really is the schema name */
if
(
likely
(
base
->
m_schema_name
==
unsafe
))
return
unsafe
;
}
}
return
NULL
;
}
const
char
*
sanitize_table_object_name
(
const
char
*
unsafe
)
{
intptr
ptr
=
(
intptr
)
unsafe
;
intptr
first
=
(
intptr
)
&
table_share_array
[
0
];
intptr
last
=
(
intptr
)
&
table_share_array
[
table_share_max
];
PFS_table_share
dummy
;
/* Check if unsafe points inside table_share_array[] */
if
(
likely
((
first
<=
ptr
)
&&
(
ptr
<
last
)))
{
intptr
offset
=
(
ptr
-
first
)
%
sizeof
(
PFS_table_share
);
intptr
from
=
my_offsetof
(
PFS_table_share
,
m_key
.
m_hash_key
);
intptr
len
=
sizeof
(
dummy
.
m_key
.
m_hash_key
);
/* Check if unsafe points inside PFS_table_share::m_key::m_hash_key */
if
(
likely
((
from
<=
offset
)
&&
(
offset
<
from
+
len
)))
{
PFS_table_share
*
base
=
(
PFS_table_share
*
)
(
ptr
-
offset
);
/* Check if unsafe really is the table name */
if
(
likely
(
base
->
m_table_name
==
unsafe
))
return
unsafe
;
}
}
return
NULL
;
}
static
void
reset_mutex_class_waits
(
void
)
...
...
storage/perfschema/pfs_instr_class.h
View file @
35d4b204
...
...
@@ -222,6 +222,8 @@ PFS_thread_class *find_thread_class(PSI_thread_key key);
PFS_thread_class
*
sanitize_thread_class
(
PFS_thread_class
*
unsafe
);
PFS_file_class
*
find_file_class
(
PSI_file_key
key
);
PFS_file_class
*
sanitize_file_class
(
PFS_file_class
*
unsafe
);
const
char
*
sanitize_table_schema_name
(
const
char
*
unsafe
);
const
char
*
sanitize_table_object_name
(
const
char
*
unsafe
);
PFS_table_share
*
find_or_create_table_share
(
PFS_thread
*
thread
,
const
char
*
schema_name
,
...
...
storage/perfschema/table_events_waits.cc
View file @
35d4b204
...
...
@@ -194,6 +194,9 @@ void table_events_waits_common::make_row(bool thread_own_wait,
PFS_instr_class
*
safe_class
;
const
char
*
base
;
const
char
*
safe_source_file
;
const
char
*
safe_table_schema_name
;
const
char
*
safe_table_object_name
;
const
char
*
safe_file_name
;
m_row_exists
=
false
;
safe_thread
=
sanitize_thread
(
pfs_thread
);
...
...
@@ -252,15 +255,19 @@ void table_events_waits_common::make_row(bool thread_own_wait,
m_row
.
m_object_type
=
"TABLE"
;
m_row
.
m_object_type_length
=
5
;
m_row
.
m_object_schema_length
=
wait
->
m_schema_name_length
;
safe_table_schema_name
=
sanitize_table_schema_name
(
wait
->
m_schema_name
);
if
(
unlikely
((
m_row
.
m_object_schema_length
==
0
)
||
(
m_row
.
m_object_schema_length
>
sizeof
(
m_row
.
m_object_schema
))))
(
m_row
.
m_object_schema_length
>
sizeof
(
m_row
.
m_object_schema
))
||
(
safe_table_schema_name
==
NULL
)))
return
;
memcpy
(
m_row
.
m_object_schema
,
wait
->
m
_schema_name
,
m_row
.
m_object_schema_length
);
memcpy
(
m_row
.
m_object_schema
,
safe_table
_schema_name
,
m_row
.
m_object_schema_length
);
m_row
.
m_object_name_length
=
wait
->
m_object_name_length
;
safe_table_object_name
=
sanitize_table_object_name
(
wait
->
m_object_name
);
if
(
unlikely
((
m_row
.
m_object_name_length
==
0
)
||
(
m_row
.
m_object_name_length
>
sizeof
(
m_row
.
m_object_name
))))
(
m_row
.
m_object_name_length
>
sizeof
(
m_row
.
m_object_name
))
||
(
safe_table_object_name
==
NULL
)))
return
;
memcpy
(
m_row
.
m_object_name
,
wait
->
m
_object_name
,
m_row
.
m_object_name_length
);
memcpy
(
m_row
.
m_object_name
,
safe_table
_object_name
,
m_row
.
m_object_name_length
);
safe_class
=
&
global_table_class
;
break
;
case
WAIT_CLASS_FILE
:
...
...
@@ -268,10 +275,12 @@ void table_events_waits_common::make_row(bool thread_own_wait,
m_row
.
m_object_type_length
=
4
;
m_row
.
m_object_schema_length
=
0
;
m_row
.
m_object_name_length
=
wait
->
m_object_name_length
;
safe_file_name
=
sanitize_file_name
(
wait
->
m_object_name
);
if
(
unlikely
((
m_row
.
m_object_name_length
==
0
)
||
(
m_row
.
m_object_name_length
>
sizeof
(
m_row
.
m_object_name
))))
(
m_row
.
m_object_name_length
>
sizeof
(
m_row
.
m_object_name
))
||
(
safe_file_name
==
NULL
)))
return
;
memcpy
(
m_row
.
m_object_name
,
wait
->
m_object
_name
,
m_row
.
m_object_name_length
);
memcpy
(
m_row
.
m_object_name
,
safe_file
_name
,
m_row
.
m_object_name_length
);
safe_class
=
sanitize_file_class
((
PFS_file_class
*
)
wait
->
m_class
);
break
;
case
NO_WAIT_CLASS
:
...
...
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