--source suite/xengine/include/have_xengine.inc --disable_warnings drop table if exists t1; --enable_warnings ## ## test adding index inplace ## # test basic add CREATE TABLE t1 (a INT, b INT, KEY ka(a), KEY kab(a,b)) ENGINE=XENGINE; INSERT INTO t1 (a, b) VALUES (1, 5); INSERT INTO t1 (a, b) VALUES (2, 6); INSERT INTO t1 (a, b) VALUES (3, 7); ALTER TABLE t1 ADD INDEX kb(b), ALGORITHM=INPLACE; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(kb) WHERE b > 5; --sorted_result SELECT * FROM t1 FORCE INDEX(kab) WHERE a > 2; DROP TABLE t1; # test add + drop (simultaneous) CREATE TABLE t1 (a INT, b INT, KEY ka(a), KEY kab(a,b)) ENGINE=XENGINE; INSERT INTO t1 (a, b) VALUES (1, 5); INSERT INTO t1 (a, b) VALUES (2, 6); INSERT INTO t1 (a, b) VALUES (3, 7); ALTER TABLE t1 ADD INDEX kb(b), DROP INDEX ka, ALGORITHM=INPLACE; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(kb) WHERE b > 5; --sorted_result SELECT * FROM t1 FORCE INDEX(kab) WHERE a > 2; DROP TABLE t1; ## test multi-drop + multi-add CREATE TABLE t1 (a INT, b INT, KEY ka(a), KEY kab(a,b)) ENGINE=XENGINE; INSERT INTO t1 (a, b) VALUES (1, 5); INSERT INTO t1 (a, b) VALUES (2, 6); INSERT INTO t1 (a, b) VALUES (3, 7); ALTER TABLE t1 DROP INDEX ka, DROP INDEX kab, ALGORITHM=INPLACE; ALTER TABLE t1 ADD INDEX kb(b), ADD INDEX kab(a,b), ALGORITHM=INPLACE; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(kb) WHERE b > 5; --sorted_result SELECT * FROM t1 FORCE INDEX(kab) WHERE a > 2; DROP TABLE t1; # test multi add + drop (simultaneous) CREATE TABLE t1 (a INT, b INT, KEY ka(a), KEY kab(a,b)) ENGINE=XENGINE; INSERT INTO t1 (a, b) VALUES (1, 5); INSERT INTO t1 (a, b) VALUES (2, 6); INSERT INTO t1 (a, b) VALUES (3, 7); ALTER TABLE t1 ADD INDEX kb(b), DROP INDEX ka, ADD INDEX kba(b,a), DROP INDEX kab, ALGORITHM=INPLACE; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(kb) WHERE b > 5; --sorted_result SELECT * FROM t1 FORCE INDEX(kba) WHERE a > 2; DROP TABLE t1; # test dropping and adding a key simultaneously w/ same name but different col CREATE TABLE t1 (a INT, b INT, KEY ka(a), KEY kab(a,b)) ENGINE=XENGINE; ALTER TABLE t1 DROP INDEX ka, ADD INDEX ka(b), ALGORITHM=INPLACE; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(ka) WHERE b > 5; --sorted_result SELECT * FROM t1 FORCE INDEX(kab) WHERE a > 2; DROP TABLE t1; ## ## test adding index inplace w/ various column types ## # test basic add CREATE TABLE t1 (pk CHAR(8) PRIMARY KEY, a VARCHAR(11), b INT UNSIGNED) ENGINE=XENGINE charset utf8 collate utf8_bin; SHOW CREATE TABLE t1; SHOW COLUMNS IN t1; INSERT INTO t1 VALUES ('aaa', '1111', 1); INSERT INTO t1 VALUES ('bbb', '2222', 2); INSERT INTO t1 VALUES ('ccc', '3333', 3); ALTER TABLE t1 ADD INDEX kab(a,b), ALGORITHM=INPLACE; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(kab) WHERE a > '2' AND b < 3; DROP TABLE t1; ## test add + drop (simultaneous) CREATE TABLE t1 (pk CHAR(8) PRIMARY KEY, a VARCHAR(11), b INT UNSIGNED) ENGINE=XENGINE charset utf8 collate utf8_bin; SHOW CREATE TABLE t1; SHOW COLUMNS IN t1; INSERT INTO t1 VALUES ('aaa', '1111', 1); INSERT INTO t1 VALUES ('bbb', '2222', 2); INSERT INTO t1 VALUES ('ccc', '3333', 3); ALTER TABLE t1 ADD INDEX kab(a,b), ALGORITHM=INPLACE; ALTER TABLE t1 ADD INDEX ka(a), DROP INDEX kab, ALGORITHM=INPLACE; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(ka) WHERE a > '2' AND b < 3; DROP TABLE t1; ### test multi-drop + multi-add CREATE TABLE t1 (pk CHAR(8) PRIMARY KEY, a VARCHAR(11), b INT UNSIGNED) ENGINE=XENGINE charset utf8 collate utf8_bin; SHOW CREATE TABLE t1; SHOW COLUMNS IN t1; INSERT INTO t1 VALUES ('aaa', '1111', 1); INSERT INTO t1 VALUES ('bbb', '2222', 2); INSERT INTO t1 VALUES ('ccc', '3333', 3); ALTER TABLE t1 ADD INDEX kab(a,b), ADD INDEX ka(a), ADD INDEX kb(b), ALGORITHM=INPLACE; ALTER TABLE t1 DROP INDEX ka, DROP INDEX kb, ALGORITHM=INPLACE; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(kab) WHERE a > '2' AND b < 3; DROP TABLE t1; ## ## test adding via CREATE/DROP index syntax ## CREATE TABLE t1 (a INT, b INT, KEY ka(a), KEY kab(a,b)) ENGINE=XENGINE; INSERT INTO t1 (a, b) VALUES (1, 5); INSERT INTO t1 (a, b) VALUES (2, 6); INSERT INTO t1 (a, b) VALUES (3, 7); CREATE INDEX kb on t1 (b); CREATE INDEX kba on t1 (b,a); DROP INDEX ka on t1; DROP INDEX kab on t1; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(kb) WHERE b > 5; --sorted_result SELECT * FROM t1 FORCE INDEX(kba) WHERE a > 2; DROP TABLE t1; # # Create tables with partitions and try to update/select from them. # --error ER_NOT_SUPPORTED_YET CREATE TABLE t1 (i INT, j INT, k INT, PRIMARY KEY (i), KEY(j)) ENGINE = XENGINE PARTITION BY KEY(i) PARTITIONS 4; # create the table again without partition should succeed CREATE TABLE t1 (i INT, j INT, k INT, PRIMARY KEY (i), KEY(j)) ENGINE = XENGINE; --disable_query_log let $max = 100; let $i = 1; while ($i <= $max) { let $insert = INSERT INTO t1 VALUES ($i, $i, $i); inc $i; eval $insert; } --enable_query_log ALTER TABLE t1 ADD INDEX kij(i,j), ALGORITHM=INPLACE; DROP INDEX kij ON t1; SHOW CREATE TABLE t1; SELECT * FROM t1 ORDER BY i LIMIT 10; SELECT COUNT(*) FROM t1; DROP TABLE t1; # test failure in prepare phase (due to collation) CREATE TABLE t1 (a INT, b TEXT); # --error 1105 ALTER TABLE t1 ADD KEY kb(b(10)); ALTER TABLE t1 ADD PRIMARY KEY(a); DROP TABLE t1; # make sure race condition between connection close and alter on another # connection is handled --echo # Establish connection con1 (user=root) connect (con1,localhost,root,,); --echo # Switch to connection con1 connection con1; CREATE TABLE t1 (i INT, j INT, PRIMARY KEY (i)) ENGINE = XENGINE; INSERT INTO t1 VALUES (1,1); # Disconnect connection 1, this starts the code path that will call # xengine_close_connection, ending the bulk load. --echo # Disconnecting on con1 disconnect con1; --echo # Establish connection con2 (user=root) connect (con2,localhost,root,,); --echo # Switch to connection con2 connection con2; # when alter table happens, it tries to close all other TABLE instances # when acquiring the exclusive lock for alter table (this happens in SQL layer) # make sure bulk_load now handles this possible race condition properly ALTER TABLE t1 ADD INDEX kj(j), ALGORITHM=INPLACE; SELECT COUNT(*) FROM t1 FORCE INDEX(PRIMARY); SELECT COUNT(*) FROM t1 FORCE INDEX(kj); DROP TABLE t1; disconnect con2; # make sure implicilty closing the alter from another session works --echo # Establish connection con1 (user=root) connect (con1,localhost,root,,); --echo # Establish connection con2 (user=root) connect (con2,localhost,root,,); --echo # Switch to connection con1 connection con1; CREATE TABLE t1 (i INT, j INT, PRIMARY KEY (i)) ENGINE = XENGINE; INSERT INTO t1 VALUES (1,1); --echo # Switch to connection con2 connection con2; # here, the bulk load hasn't been completed yet, and we are in conn2 # therefore select count returns 0 SELECT COUNT(*) FROM t1 FORCE INDEX(PRIMARY); # implicilty close the table from connection 2 ALTER TABLE t1 ADD INDEX kj(j), ALGORITHM=INPLACE; SELECT COUNT(*) FROM t1 FORCE INDEX(PRIMARY); SELECT COUNT(*) FROM t1 FORCE INDEX(kj); DROP TABLE t1; connection default; SET @prior_xengine_strict_collation_check= @@xengine_strict_collation_check; SET global xengine_strict_collation_check = off; CREATE TABLE t1 (a VARCHAR(80)) ENGINE=XENGINE charset latin1; INSERT INTO t1 (a) VALUES (REPEAT("a", 80)); INSERT INTO t1 (a) VALUES (REPEAT("a", 80)); INSERT INTO t1 (a) VALUES (REPEAT("a", 80)); INSERT INTO t1 (a) VALUES (REPEAT("a", 80)); ALTER TABLE t1 ADD INDEX ka(a), ALGORITHM=INPLACE; SHOW CREATE TABLE t1; CHECK TABLE t1; --sorted_result SELECT * FROM t1 FORCE INDEX(ka) WHERE a > ""; DROP TABLE t1; SET global xengine_strict_collation_check = @prior_xengine_strict_collation_check; # Test to make sure index statistics are updating properly CREATE TABLE t1 (i INT, j INT, PRIMARY KEY (i)) ENGINE = XENGINE; --disable_query_log let $max = 100; let $i = 1; while ($i <= $max) { let $insert = INSERT INTO t1 VALUES ($i, $i); inc $i; eval $insert; } --enable_query_log set information_schema_stats_expiry = 0; set global xengine_force_flush_memtable_now=1; --let $data_length_old = query_get_value("select INDEX_LENGTH from information_schema.tables where table_schema=database() and table_name='t1'", INDEX_LENGTH, 1) ## uncomment to see the actual values #--replace_column 8 # #SHOW TABLE STATUS WHERE name LIKE 't1'; # Now do an alter and see what happens ALTER TABLE t1 ADD INDEX kj(j), ALGORITHM=INPLACE; --let $data_length_new = query_get_value("select INDEX_LENGTH from information_schema.tables where table_schema=database() and table_name='t1'", INDEX_LENGTH, 1) --disable_query_log --eval select $data_length_old < $data_length_new as "larger" --source include/restart_mysqld.inc --source include/wait_until_connected_again.inc --let $data_length_new = query_get_value("select INDEX_LENGTH from information_schema.tables where table_schema=database() and table_name='t1'", INDEX_LENGTH, 1) --disable_query_log --eval select $data_length_old < $data_length_new as "larger" analyze table t1; --let $data_length_new = query_get_value("select INDEX_LENGTH from information_schema.tables where table_schema=database() and table_name='t1'", INDEX_LENGTH, 1) --disable_query_log --eval select $data_length_old < $data_length_new as "larger" --source include/restart_mysqld.inc --source include/wait_until_connected_again.inc --let $data_length_new = query_get_value("select INDEX_LENGTH from information_schema.tables where table_schema=database() and table_name='t1'", INDEX_LENGTH, 1) --disable_query_log --eval select $data_length_old < $data_length_new as "larger" # verifying multiple analyze table won't change stats --disable_query_log let $max = 10; let $i = 1; while ($i <= $max) { let $analyze = ANALYZE TABLE t1; inc $i; eval $analyze; } --enable_query_log --let $data_length_new2 = query_get_value("select INDEX_LENGTH from information_schema.tables where table_schema=database() and table_name='t1'", INDEX_LENGTH, 1) --eval select $data_length_new2 < $data_length_new * 1.5 as "same" --enable_query_log ## uncomment to see the actual values #--replace_column 8 # #SHOW TABLE STATUS WHERE name LIKE 't1'; DROP TABLE t1; # Test that fast secondary index creation updates cardinality properly CREATE TABLE t1 (i INT PRIMARY KEY, j INT) ENGINE = XENGINE; INSERT INTO t1 VALUES (1,2), (2,4), (3,6), (4,8), (5,10); ALTER TABLE t1 ADD INDEX kj(j), ALGORITHM=INPLACE; # Flush memtable out to SST SET GLOBAL xengine_force_flush_memtable_now = 1; # Return the data for the primary key of t1 --replace_column 1 # 2 # 3 SSTNAME 5 # 6 # 7 # 8 # 9 # SELECT * FROM INFORMATION_SCHEMA.XENGINE_INDEX_FILE_MAP WHERE INDEX_NUMBER = (SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.XENGINE_DDL WHERE TABLE_NAME = 't1' AND INDEX_NAME = "PRIMARY"); # Return the data for the secondary index of t1 --replace_column 1 # 2 # 3 SSTNAME 5 # 6 # 7 # 8 # 9 # SELECT * FROM INFORMATION_SCHEMA.XENGINE_INDEX_FILE_MAP WHERE INDEX_NUMBER = (SELECT INDEX_NUMBER FROM INFORMATION_SCHEMA.XENGINE_DDL WHERE TABLE_NAME = 't1' AND INDEX_NAME = "kj"); # cleanup DROP TABLE t1; # https://github.com/facebook/mysql-5.6/issues/602 # Add then drop same index should be optimized out. CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c INT, KEY kbc(b,c)) ENGINE = XENGINE; INSERT INTO t1 (a,b,c) VALUES (1,1,1); INSERT INTO t1 (a,b,c) VALUES (2,2,2); INSERT INTO t1 (a,b,c) VALUES (3,3,3); SHOW CREATE TABLE t1; ALTER TABLE t1 DROP INDEX kbc, ADD INDEX kbc(b,c), ALGORITHM=INPLACE; ALTER TABLE t1 DROP INDEX kbc; DROP TABLE t1; # Make sure make index unique->none unique is ok CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, c INT, UNIQUE KEY kbc(b,c)) ENGINE = XENGINE; INSERT INTO t1 (a,b,c) VALUES (1,1,1); INSERT INTO t1 (a,b,c) VALUES (2,2,2); INSERT INTO t1 (a,b,c) VALUES (3,3,3); SHOW CREATE TABLE t1; ALTER TABLE t1 DROP INDEX kbc, ADD INDEX kbc(b,c), ALGORITHM=INPLACE; SELECT SLEEP(5); ALTER TABLE t1 DROP INDEX kbc; DROP TABLE t1; # Make sure changing key part prefix length causes index rebuild as well. CREATE TABLE t1 ( a INT PRIMARY KEY, b varchar(10), index kb(b(5)) ) ENGINE = XENGINE charset utf8 collate utf8_bin; INSERT INTO t1 (a,b) VALUES (1,'1111122222'); INSERT INTO t1 (a,b) VALUES (2,'2222233333'); INSERT INTO t1 (a,b) VALUES (3,'3333344444'); --let $start_max_index_id = query_get_value(SELECT * from INFORMATION_SCHEMA.XENGINE_GLOBAL_INFO where type = 'MAX_INDEX_ID', VALUE, 1) ALTER TABLE t1 DROP INDEX kb, ADD INDEX kb(b(8)), ALGORITHM=INPLACE; SELECT * FROM t1 FORCE INDEX(kb); --let $end_max_index_id = query_get_value(SELECT * from INFORMATION_SCHEMA.XENGINE_GLOBAL_INFO where type = 'MAX_INDEX_ID', VALUE, 1) if ($end_max_index_id <= $start_max_index_id) { echo Max index ID did not increase; } SHOW CREATE TABLE t1; DROP TABLE t1; --source suite/xengine/include/check_xengine_log_error.inc