--echo # --echo # Test that query preparation is able to make plans for executing --echo # a query on a secondary storage engine. --echo # --disable_query_log eval INSTALL PLUGIN mock SONAME '$MOCK_PLUGIN'; --enable_query_log CREATE TABLE t1(id INT PRIMARY KEY, x INT, y INT); INSERT INTO t1 VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9); CREATE INDEX t1_x ON t1(x); --sorted_result SELECT * FROM t1; CREATE TABLE t2(id INT PRIMARY KEY, z INT); INSERT INTO t2 VALUES (1, 2), (3, 4), (5, 6); CREATE VIEW v1 AS SELECT t1.id, t1.x, t2.z FROM t1, t2 WHERE t1.id = t2.id; SELECT * FROM v1; CREATE TABLE t_primary_only(id INT PRIMARY KEY, x INT); INSERT INTO t_primary_only VALUES (1, 1), (2, 2); ALTER TABLE t1 SECONDARY_ENGINE MOCK; ALTER TABLE t2 SECONDARY_ENGINE MOCK; # t1 has not been loaded into the secondary engine yet. FLUSH STATUS; SELECT * FROM t1; PREPARE ps FROM 'SELECT * FROM t1'; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP PREPARE ps; # Load and unload t1. FLUSH STATUS; ALTER TABLE t1 SECONDARY_LOAD; PREPARE ps FROM 'SELECT * FROM t1'; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; ALTER TABLE t1 SECONDARY_UNLOAD; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP PREPARE ps; ALTER TABLE t1 SECONDARY_LOAD; ALTER TABLE t2 SECONDARY_LOAD; # The queries should now use the mock engine, which always returns an # empty result. FLUSH STATUS; SELECT * FROM t1; PREPARE ps FROM 'SELECT * FROM t1'; EXECUTE ps; EXECUTE ps; FLUSH TABLES; SELECT * FROM t1; FLUSH TABLES; EXECUTE ps; DROP PREPARE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; # The row count estimate should be available (via the primary table). ANALYZE TABLE t1; EXPLAIN SELECT * FROM t1; # Some queries that should use the secondary engine. FLUSH STATUS; SELECT * FROM t1 JOIN t2 USING (id); SELECT * FROM t1 WHERE t1.x IN (SELECT t2.z FROM t2); SELECT SUM(x) FROM t1 GROUP BY y; SELECT (SELECT MAX(x) FROM t1), (SELECT MIN(z) FROM t2), s FROM (SELECT SUM(z) AS s FROM t2) AS dt; SELECT * FROM v1; SELECT * FROM v1, t2 WHERE v1.id = t2.id; SELECT SUM(x) FROM v1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; # A forced index scan can be offloaded, since it's just a hint. FLUSH STATUS; SELECT x FROM t1 FORCE INDEX (t1_x); PREPARE ps FROM 'SELECT x FROM t1 FORCE INDEX (t1_x)'; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SET @my_use_secondary_engine = @@use_secondary_engine; SET @@use_secondary_engine = FORCED; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SET @@use_secondary_engine = @my_use_secondary_engine; # The query should not be offloaded to the secondary engine if LOCK # TABLES mode is active. FLUSH STATUS; PREPARE ps FROM 'SELECT * FROM t1'; LOCK TABLES t1 READ; SELECT * FROM t1; EXECUTE ps; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; UNLOCK TABLES; SELECT * FROM t1; EXECUTE ps; EXECUTE ps; DROP PREPARE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; # The query should not be offloaded to the secondary engine in # multi-statement transaction mode. FLUSH STATUS; PREPARE ps FROM 'SELECT * FROM t1'; BEGIN; SELECT * FROM t1; EXECUTE ps; COMMIT; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; FLUSH STATUS; START TRANSACTION; SELECT * FROM t1; EXECUTE ps; COMMIT; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; FLUSH STATUS; SET @@autocommit = 0; SELECT * FROM t1; EXECUTE ps; SET @@autocommit = 1; COMMIT; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SELECT * FROM t1; EXECUTE ps; DROP PREPARE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; FLUSH STATUS; BEGIN; PREPARE ps FROM 'SELECT * FROM t1'; EXECUTE ps; COMMIT; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP PREPARE ps; # Queries that access at least one table that is not available in a # secondary engine, should not be offloaded. SELECT * FROM t1, t_primary_only tp WHERE t1.id = tp.id; PREPARE ps FROM 'SELECT * FROM t1, t_primary_only tp WHERE t1.id = tp.id'; EXECUTE ps; EXECUTE ps; DROP PREPARE ps; SELECT * FROM t1, t2, t_primary_only tp WHERE t1.id = t2.id AND t2.id = tp.id; # Queries that access schema tables should not be offloaded. EXPLAIN SELECT * FROM t1, INFORMATION_SCHEMA.COLUMN_PRIVILEGES t2; # It should be possible to have tables with an auto-increment column # in a secondary engine. CREATE TABLE t_with_autoinc(id INT PRIMARY KEY AUTO_INCREMENT, x INT) SECONDARY_ENGINE MOCK; INSERT INTO t_with_autoinc(x) VALUES (4), (5), (6); ALTER TABLE t_with_autoinc SECONDARY_LOAD; SELECT * FROM t_with_autoinc; DROP TABLE t_with_autoinc; # Tables that are partitioned in the primary engine can also have # secondary tables. CREATE TABLE t_partitioned(id INT PRIMARY KEY, x INT) SECONDARY_ENGINE MOCK PARTITION BY HASH(id); INSERT INTO t_partitioned VALUES (1, 2), (2, 3), (3, 4), (4, 5); ALTER TABLE t_partitioned SECONDARY_LOAD; SELECT * FROM t_partitioned; DROP TABLE t_partitioned; # Multiple queries in a single statement. DELIMITER |; FLUSH STATUS; SELECT * FROM t1; PREPARE ps FROM 'SELECT * FROM t1'; EXECUTE ps; SELECT * FROM t1, t_primary_only tp WHERE t1.id = tp.id; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; ALTER TABLE t1 SECONDARY_UNLOAD; SELECT * FROM t1; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; ALTER TABLE t1 SECONDARY_LOAD; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP PREPARE ps| DELIMITER ;| # Prepared statement with an argument. FLUSH STATUS; PREPARE ps FROM 'SELECT x FROM t1 WHERE id = ?'; SET @a=1; EXECUTE ps USING @a; EXECUTE ps USING @a; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; ALTER TABLE t1 SECONDARY_UNLOAD; EXECUTE ps USING @a; EXECUTE ps USING @a; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; ALTER TABLE t1 SECONDARY_LOAD; EXECUTE ps USING @a; EXECUTE ps USING @a; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP PREPARE ps; # Test a query that returns multiple rows, even with the mock engine. FLUSH STATUS; --sorted_result SELECT JSON_EXTRACT(j, '$') FROM (SELECT '[]' AS j FROM DUAL UNION ALL SELECT '{}' FROM DUAL) AS dt LEFT JOIN t1 ON (TRUE); SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; # If an offloaded query fails during execution, after optimization, it # is not automatically reprepared. FLUSH STATUS; --error ER_INVALID_JSON_TEXT_IN_PARAM SELECT JSON_EXTRACT(j, '$') FROM (SELECT '[]' AS j FROM DUAL UNION ALL SELECT 'not-json' FROM DUAL) AS dt LEFT JOIN t1 ON (TRUE); SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; FLUSH STATUS; PREPARE ps FROM "SELECT JSON_EXTRACT(j, '$') FROM (SELECT '[]' AS j FROM DUAL UNION ALL SELECT 'not-json' FROM DUAL) AS dt LEFT JOIN t1 ON (TRUE)"; --error ER_INVALID_JSON_TEXT_IN_PARAM EXECUTE ps; --error ER_INVALID_JSON_TEXT_IN_PARAM EXECUTE ps; DROP PREPARE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; # Queries inside a procedure should not be offloaded. FLUSH STATUS; CREATE PROCEDURE p1() SELECT COUNT(*) FROM t1; CALL p1(); SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; PREPARE ps1 FROM 'SELECT * FROM t1'; EXECUTE ps1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; CREATE PROCEDURE p2() EXECUTE ps1; CREATE PROCEDURE p3() PREPARE ps2 FROM 'SELECT * FROM t1'; FLUSH STATUS; CALL p2(); SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; CALL p3(); SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; EXECUTE ps1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; EXECUTE ps2; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP PREPARE ps1; DROP PREPARE ps2; DROP PROCEDURE p1; DROP PROCEDURE p2; DROP PROCEDURE p3; # Queries inside a trigger should not be offloaded. FLUSH STATUS; CREATE TABLE t_with_trigger(x INT); CREATE TRIGGER tr AFTER INSERT ON t_with_trigger FOR EACH ROW SELECT COUNT(*) FROM t1 INTO @a; INSERT INTO t_with_trigger VALUES (1); SELECT @a; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t_with_trigger; # Non-existent secondary engine. CREATE TABLE t_nonexistent(x INT) SECONDARY_ENGINE NONEXISTENT; INSERT INTO t_nonexistent VALUES (1); FLUSH STATUS; SELECT * FROM t_nonexistent; SELECT * FROM t1 a, t_nonexistent b WHERE a.id = b.x; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t_nonexistent; # Same secondary engine specified with different case and differing # number of trailing blanks. CREATE TABLE t_case1(x INT) SECONDARY_ENGINE 'MOCK'; CREATE TABLE t_case2(y INT) SECONDARY_ENGINE 'mock '; CREATE TABLE t_case3(z INT) SECONDARY_ENGINE 'MoCk '; INSERT INTO t_case1 VALUES (1); INSERT INTO t_case2 VALUES (2); INSERT INTO t_case3 VALUES (3); ALTER TABLE t_case1 SECONDARY_LOAD; ALTER TABLE t_case2 SECONDARY_LOAD; ALTER TABLE t_case3 SECONDARY_LOAD; FLUSH STATUS; SELECT * FROM t_case1, t_case2, t_case3; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t_case1, t_case2, t_case3; # Queries that invoke stored routines should not be offloaded. CREATE TABLE tf(x INT) SECONDARY_ENGINE MOCK; INSERT INTO tf VALUES (123); ALTER TABLE tf SECONDARY_LOAD; DELIMITER |; CREATE FUNCTION f1() RETURNS INT DETERMINISTIC BEGIN DECLARE i INT; SELECT x INTO i FROM tf; RETURN i; END| CREATE FUNCTION f2() RETURNS INT DETERMINISTIC BEGIN INSERT INTO tf VALUES (234); RETURN 1; END| DELIMITER ;| FLUSH STATUS; SELECT f1(); SELECT f2(); SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; --sorted_result SELECT * FROM tf; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE tf; # Drop a table between two executions. CREATE TABLE t_dropped (x INT) SECONDARY_ENGINE MOCK; ALTER TABLE t_dropped SECONDARY_LOAD; PREPARE ps FROM 'SELECT * FROM t_dropped'; EXECUTE ps; DROP TABLE t_dropped; --error ER_NO_SUCH_TABLE EXECUTE ps; DROP PREPARE ps; # Cleanup. DROP VIEW v1; DROP TABLE t1, t2, t_primary_only; --echo # --echo # Rudimentary tests for use_secondary_engine system variable. --echo # SET @my_use_secondary_engine = @@use_secondary_engine; CREATE TABLE t1 (a INT) SECONDARY_ENGINE MOCK; INSERT INTO t1 VALUES (1); ALTER TABLE t1 SECONDARY_LOAD; FLUSH STATUS; --echo # The row shall be returned from the primary storage engine. SET @@use_secondary_engine = OFF; SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; --echo # The mock storage engine does not return any rows. SET @@use_secondary_engine = FORCED; SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SET @@use_secondary_engine = ON; SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; --echo # An error shall be returned if table is not loaded. ALTER TABLE t1 SECONDARY_UNLOAD; SET @@use_secondary_engine = FORCED; --error ER_SECONDARY_ENGINE SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SET @@use_secondary_engine = ON; SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t1; SET @@use_secondary_engine = @my_use_secondary_engine; --echo # --echo # Queries not referencing any base tables shall be executed without --echo # without even if use_secondary_engine is FORCED. --echo # SET @my_use_secondary_engine = @@use_secondary_engine; SET @@use_secondary_engine = FORCED; CREATE VIEW v as SELECT 1; SELECT * FROM v; SELECT 1; SELECT COUNT(*) FROM (SELECT 1) AS dt; DROP VIEW v; SET @@use_secondary_engine = @my_use_secondary_engine; --echo # --echo # Attempt to force query on secondary engine even if its referenced --echo # table has no secondary engine defined. --echo # SET @my_use_secondary_engine = @@use_secondary_engine; SET @@use_secondary_engine = FORCED; CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1); FLUSH STATUS; --error ER_SECONDARY_ENGINE SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SET @@use_secondary_engine = ON; SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t1; SET @@use_secondary_engine = @my_use_secondary_engine; --echo # --echo # Attempt to force query on secondary engine if one of its referenced --echo # table has a secondary engine while another table has none. --echo # SET @my_use_secondary_engine = @@use_secondary_engine; SET @@use_secondary_engine = FORCED; CREATE TABLE t1 (a INT) SECONDARY_ENGINE MOCK; CREATE TABLE t2 (a INT); INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES (2); ALTER TABLE t1 SECONDARY_LOAD; FLUSH STATUS; SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; --error ER_SECONDARY_ENGINE SELECT * FROM t2; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; --error ER_SECONDARY_ENGINE SELECT * FROM t1,t2; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; ALTER TABLE t1 SECONDARY_UNLOAD; --error ER_SECONDARY_ENGINE SELECT * FROM t1,t2; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t1,t2; SET @@use_secondary_engine = @my_use_secondary_engine; --echo # --echo # Attempt to force query referencing temporary table on secondary engine. --echo # SET @my_use_secondary_engine = @@use_secondary_engine; SET @@use_secondary_engine = FORCED; CREATE TEMPORARY TABLE t1 (a INT); FLUSH STATUS; --error ER_SECONDARY_ENGINE SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t1; SET @@use_secondary_engine = @my_use_secondary_engine; --echo # --echo # Change use_secondary_engine across execution of prepared statements. --echo # SET @my_use_secondary_engine = @@use_secondary_engine; SET @@use_secondary_engine = FORCED; CREATE TABLE t1 (a INT) SECONDARY_ENGINE MOCK; FLUSH STATUS; PREPARE ps FROM "SELECT * FROM t1"; --error ER_SECONDARY_ENGINE EXECUTE ps; SET @@use_secondary_engine = OFF; EXECUTE ps; --echo # Load table into secondary engine. ALTER TABLE t1 SECONDARY_LOAD; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SET @@use_secondary_engine = ON; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SET @@use_secondary_engine = FORCED; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; --echo # Unload table from secondary engine. ALTER TABLE t1 SECONDARY_UNLOAD; SET @@use_secondary_engine = ON; EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SET @@use_secondary_engine = FORCED; --error ER_SECONDARY_ENGINE EXECUTE ps; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP PREPARE ps; DROP TABLE t1; SET @@use_secondary_engine = @my_use_secondary_engine; --echo # --echo # Set use_secondary_engine as a hint. --echo # SET @my_use_secondary_engine = @@use_secondary_engine; SET @@use_secondary_engine = OFF; CREATE TABLE t1 (a INT) SECONDARY_ENGINE MOCK; INSERT INTO t1 VALUES (1); FLUSH STATUS; SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; ALTER TABLE t1 SECONDARY_LOAD; SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SELECT /*+ SET_VAR(use_secondary_engine = ON) */ * FROM t1; SET @@use_secondary_engine = @my_use_secondary_engine; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SELECT /*+ SET_VAR(use_secondary_engine = OFF) */ * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t1; SET @@use_secondary_engine = @my_use_secondary_engine; --echo # --echo # Bug#28311801: THE GLOBAL VALUE OF SECONDARY_ENGINE_EXECUTION_COUNT --echo # IS ALWAYS ZERO --echo # CREATE TABLE t (x INT) SECONDARY_ENGINE MOCK; ALTER TABLE t SECONDARY_LOAD; let $count_before = query_get_value( SHOW GLOBAL STATUS LIKE 'Secondary_engine_execution_count', Value, 1); SELECT * FROM t; FLUSH STATUS; let $count_after = query_get_value( SHOW GLOBAL STATUS LIKE 'Secondary_engine_execution_count', Value, 1); expr $execution_count = $count_after - $count_before; eval SELECT $execution_count; DROP TABLE t; --echo # --echo # Bug#28556942: ADD USING SECONDARY ENGINE TO EXPLAIN --echo # CREATE TABLE t1 (a INT) SECONDARY_ENGINE MOCK; --echo # Before table is loaded, the secondary engine should not be used. ANALYZE TABLE t1; EXPLAIN SELECT * FROM t1; EXPLAIN FORMAT=JSON SELECT * FROM t1; ALTER TABLE t1 SECONDARY_LOAD; --echo # After table is loaded, the secondary engine should be used. ANALYZE TABLE t1; EXPLAIN SELECT * FROM t1; EXPLAIN FORMAT=JSON SELECT * FROM t1; DROP TABLE t1; --echo # --echo # Load only a subset of columns into secondary engine. --echo # SET @my_use_secondary_engine = @@use_secondary_engine; CREATE TABLE t1 ( pk INT PRIMARY KEY AUTO_INCREMENT, a INT, b INT NOT SECONDARY, c INT, d INT NOT SECONDARY ) SECONDARY_ENGINE MOCK; CREATE TABLE t2 ( pk INT PRIMARY KEY AUTO_INCREMENT, e INT, f INT NOT SECONDARY, g INT, h INT NOT SECONDARY ) SECONDARY_ENGINE MOCK; INSERT INTO t1 (a, b, c, d) VALUES (1,1,1,1), (1,1,1,1), (2,2,2,2); INSERT INTO t2 (e, f, g, h) VALUES (2,2,2,2), (2,2,2,2), (3,3,3,3); ALTER TABLE t1 SECONDARY_LOAD; ALTER TABLE t2 SECONDARY_LOAD; --echo # Statements which should be sent to primary engine since not all columns --echo # are in secondary engine. CREATE VIEW v1 as SELECT * FROM t1; CREATE VIEW v2 as SELECT t1.a, t2.f FROM t1, t2; SELECT * FROM t1; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ * FROM t1; SELECT 1 FROM t1 WHERE b=1; SELECT 1 FROM t1 GROUP BY b; SELECT 1 FROM t1 ORDER BY b; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ 1 FROM t1 WHERE b=1; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ 1 FROM t1 GROUP BY b; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ 1 FROM t1 ORDER BY b; SELECT * FROM v1; SELECT SUM(b) FROM v1; SELECT 1 FROM v1 WHERE b=1; SELECT 1 FROM v1 GROUP BY b; SELECT 1 FROM v1 ORDER BY b; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ * FROM v1; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ SUM(b) FROM v1; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ 1 FROM v1 WHERE b=1; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ 1 FROM v1 GROUP BY b; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ 1 FROM v1 ORDER BY b; --sorted_result SELECT t1.a, t2.f FROM t1, t2; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ t1.a, t2.f FROM t1, t2; --sorted_result SELECT * FROM v2; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ * FROM v2; --echo # Statements which should be sent to the secondary engine since all --echo # columns are in secondary engine. SET @@use_secondary_engine = FORCED; CREATE VIEW v3 as SELECT a, c FROM t1; CREATE VIEW v4 as SELECT t1.a, t1.c, t2.e, t2.g FROM t1, t2; SELECT a, c FROM t1; SELECT 1 FROM t1 WHERE a=1; SELECT * FROM v3; SELECT t1.a, t1.c, t2.e, t2.g FROM t1, t2; SELECT * FROM v4; DROP VIEW v1, v2, v3, v4; DROP TABLE t1, t2; SET @@use_secondary_engine = @my_use_secondary_engine; --echo # --echo # NOT SECONDARY on partitioned table --echo # CREATE TABLE t1 (a INT PRIMARY KEY NOT SECONDARY, b INT DEFAULT 10) PARTITION BY RANGE (a) ( PARTITION p0 VALUES LESS THAN (1), PARTITION p1 VALUES LESS THAN (2), PARTITION p2 VALUES LESS THAN (3), PARTITION p3 VALUES LESS THAN (4), PARTITION p4 VALUES LESS THAN (5), PARTITION p5 VALUES LESS THAN (6), PARTITION max VALUES LESS THAN MAXVALUE); INSERT INTO t1(a) VALUES (-1),(0),(1),(2),(3),(4),(5),(6),(7),(8); ALTER TABLE t1 SECONDARY_ENGINE=MOCK; ALTER TABLE t1 SECONDARY_LOAD; ANALYZE TABLE t1; FLUSH STATUS; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ a FROM t1; SELECT a FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SELECT b FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ b FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t1; --echo # --echo # Use NOT SECONDARY as comment. --echo # CREATE TABLE t1 (a INT /* NOT SECONDARY */, b INT ) SECONDARY_ENGINE MOCK; INSERT INTO t1 VALUES (1,1); ALTER TABLE t1 SECONDARY_LOAD; SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ a FROM t1; FLUSH STATUS; SELECT a FROM t1; SELECT * FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t1; --echo # --echo # Use NOT SECONADRY with other constraint on column. --echo # CREATE TABLE t1 (a INT, b INT NOT SECONDARY UNIQUE KEY) SECONDARY_ENGINE MOCK; INSERT INTO t1 VALUES (1, 1); ALTER TABLE t1 SECONDARY_LOAD; FLUSH STATUS; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ * FROM t1; SELECT a FROM t1; --error ER_SECONDARY_ENGINE SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ b FROM t1; SHOW SESSION STATUS LIKE 'Secondary_engine_execution_count'; DROP TABLE t1; --echo # Add NON SECONDARY and do not use SECONDARY_ENGINE AT CREATE CREATE TABLE t1 (a INT NOT SECONDARY, b INT); INSERT INTO t1 VALUES (1,1); SELECT a FROM t1; SELECT b FROM t1; SELECT * FROM t1; DROP TABLE t1; --echo # --echo # Bug#28738100: SECONDARY ENGINE RETURNS WRONG RESULT WITH IS NULL CLAUSE --echo # # Enable special handling of IS NULL for this test case. SET @saved_sql_auto_is_null = @@sql_auto_is_null; SET @@sql_auto_is_null = 1; CREATE TABLE t(a INT PRIMARY KEY AUTO_INCREMENT) SECONDARY_ENGINE MOCK; ALTER TABLE t SECONDARY_LOAD; INSERT INTO t VALUES (); ANALYZE TABLE t; # Verify that a IS NULL is rewritten to a = last_insert_id(). EXPLAIN SELECT * FROM t WHERE a IS NULL; DROP TABLE t; # Restore regular handling of IS NULL. SET @@sql_auto_is_null = @saved_sql_auto_is_null; --echo # Bug#29288023: Join condition is substituted with REF access CREATE TABLE t1(f1 int, f11 int); CREATE TABLE t2(f2 int, f22 int); INSERT INTO t1 VALUES(1,1),(2,2),(3,3),(5,5),(9,9),(7,7); INSERT INTO t2 VALUES(1,1),(3,3),(2,2),(4,4),(8,8),(6,6); let $query= SELECT * FROM t1 JOIN (SELECT f2, SUM(f22) AS b FROM t2 GROUP BY f2) AS dt ON t1.f1=dt.f2; --echo Explain should show for indexes on derived tables ANALYZE TABLE t1, t2; eval EXPLAIN $query; ALTER TABLE t1 SECONDARY_ENGINE=MOCK; ALTER TABLE t1 SECONDARY_LOAD; ALTER TABLE t2 SECONDARY_ENGINE=MOCK; ALTER TABLE t2 SECONDARY_LOAD; ANALYZE TABLE t1, t2; --echo Secondary engine does not support indexes on derived tables eval EXPLAIN $query; DROP TABLE t1, t2; CREATE TABLE t1(x INT, y INT, z INT, c INT, d INT); INSERT INTO t1 VALUES (1, 5, 2, 2, 3), (2, 2, 5, 2, 3), (3, 5, 5, 2, 3), (4, 2, 5, 2, 3), (2, 3, 4, 2, 3), (7, 6, 5, 2, 3), (8, 9, 5, 2, 3), (9, 6, 5, 2, 3), (10, 7, 5, 2, 3), (11, 6, 5, 2, 3), (12, 7, 5, 2, 3), (13, -1, 5, 2, 3), (14, 7, 5, 2, 3), (15, 8, 5, 2, 3), (16, 4, 5, 2, 3), (17, 7, 5, 2, 3), (18, 7, 5, 2, 3), (19, 17, 5, 2, 3), (20, 17, 5, 2, 3), (21, 5, -1, 2, 3), (22, 5, 5, 2, 3); ALTER TABLE t1 SECONDARY_ENGINE=MOCK; ALTER TABLE t1 SECONDARY_LOAD; ANALYZE TABLE t1; EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE x < 7 LIMIT 20) tt1, (SELECT * FROM t1 WHERE x < y LIMIT 20) tt2 WHERE tt1.x> 5 and tt1.x=tt2.x; DROP TABLE t1; --echo # --echo # Bug#29994087: SIG11 AT MATERIALIZEITERATOR::INIT() IN --echo # SQL/COMPOSITE_ITERATORS.CC --echo # CREATE TABLE t (a INT, b INT) SECONDARY_ENGINE MOCK; ALTER TABLE t SECONDARY_LOAD; SELECT 1 FROM t WHERE (1, 2) IN (SELECT 3, 4 UNION SELECT 5, 6) OR b <= 10; DROP TABLE t; --echo # --echo # Bug#29615190: SELECTS ON TABLES OFFLOADED TO SECONDARY ENGINE ARE --echo # WRITTEN TWICE TO THE MYSQLD GENERAL LOG --echo # CREATE TABLE t(x INT) SECONDARY_ENGINE MOCK; ALTER TABLE t SECONDARY_LOAD; SET @saved_general_log = @@global.general_log; SET @saved_log_output = @@global.log_output; SET GLOBAL general_log = 1; SET GLOBAL log_output = 'table'; TRUNCATE TABLE mysql.general_log; SELECT * FROM t; # Expect the query to be written once to the general log (or twice # under ps protocol - once for preparation and once for execution). --disable_query_log eval SELECT COUNT(*) - $PS_PROTOCOL AS statement_count FROM mysql.general_log WHERE argument = 'SELECT * FROM t'; --enable_query_log TRUNCATE TABLE mysql.general_log; PREPARE ps FROM 'SELECT * FROM t'; SELECT COUNT(*) FROM mysql.general_log WHERE argument = 'SELECT * FROM t'; EXECUTE ps; SELECT COUNT(*) FROM mysql.general_log WHERE argument = 'SELECT * FROM t'; DROP PREPARE ps; TRUNCATE TABLE mysql.general_log; SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ * FROM t; # Expect the query to be written once to the general log (or twice # under ps protocol - once for preparation and once for execution). --disable_query_log eval SELECT COUNT(*) - $PS_PROTOCOL AS statement_count FROM mysql.general_log WHERE argument LIKE 'SELECT % * FROM t'; --enable_query_log TRUNCATE TABLE mysql.general_log; PREPARE ps FROM 'SELECT /*+ SET_VAR(use_secondary_engine = FORCED) */ * FROM t'; SELECT COUNT(*) FROM mysql.general_log WHERE argument LIKE 'SELECT % * FROM t'; EXECUTE ps; SELECT COUNT(*) FROM mysql.general_log WHERE argument LIKE 'SELECT % * FROM t'; DROP PREPARE ps; SET GLOBAL general_log = @saved_general_log; SET GLOBAL log_output = @saved_log_output; TRUNCATE TABLE mysql.general_log; DROP TABLE t; --disable_query_log UNINSTALL PLUGIN mock; --enable_query_log