mysql-server/mysql-test/t/hypergraph_bugs.test
2025-03-05 14:31:37 +07:00

1378 lines
40 KiB
Text

--source include/have_hypergraph.inc
--source include/have_optimizer_trace.inc
--source include/elide_costs.inc
# This should have been a unit test. But unit tests do not have framework
# for prepared statements yet. So we are adding this.
--echo #
--echo # Bug#34402003: HYPERGRAPH BUG: Offload issue with execute statement.
--echo #
CREATE TABLE t1(a INT);
CREATE TABLE t2(a INT);
CREATE TABLE t3(a INT);
INSERT INTO t1 VALUES (1),(2),(5);
INSERT INTO t2 VALUES (2);
INSERT INTO t3 VALUES (3);
ANALYZE TABLE t1, t2, t3;
# Hypergraph should be able to use the multiple equality (5, t1.a, t2.a).
# So, the join condition (t1.a=t2.a) should not be seen in the final plan.
# Instead, it should see filters (t1.a=5) and (t2.a=5).
SET optimizer_trace='enabled=on';
let $query = SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.a JOIN t3 ON t1.a=5;
eval PREPARE stmt FROM "EXPLAIN FORMAT=tree $query";
eval EXECUTE stmt;
# Check that we are using the optimized join condition for generating the
# plan i.e it should be using multiple equalities that are established during
# optimization.
SELECT
IF(TRACE LIKE '%Left join [companion set %] (extra join condition = (t1.a = 5) AND (t2.a = 5))%',
'OK', TRACE)
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
eval PREPARE stmt FROM "$query";
eval EXECUTE stmt;
SET optimizer_trace="enabled=off";
DROP TABLE t1,t2,t3;
CREATE TABLE t0 (a0 INTEGER);
CREATE TABLE t1 (a1 INTEGER);
CREATE TABLE t2 (a2 INTEGER);
CREATE TABLE t3 (a3 INTEGER);
INSERT INTO t0 VALUES (0),(1);
INSERT INTO t1 VALUES (0),(1);
INSERT INTO t2 VALUES (1);
INSERT INTO t3 VALUES (1);
# Hypergraph should be able to detect that a1=5 cannot be true resulting
# in Zero rows access path for right side of the join.
EXPLAIN FORMAT=tree SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
DROP TABLE t0,t1,t2,t3;
--echo #
--echo # Bug#34401789: Enable constant propagation in conditions
--echo # for hypergraph optimizer
--echo #
CREATE TABLE t1 (f1 INTEGER);
EXPLAIN FORMAT=tree
SELECT f1 FROM t1 GROUP BY f1 HAVING f1 = 10 AND f1 <> 11;
DROP TABLE t1;
# This should have been a unit test. But unit tests do not have framework
# for type "year" yet.
# We are basically testing that "f1" in the non-equality predicate gets
# substituted with value "1" propagated from "f1 = 1" predicate which
# will make the condition to be always true.
--echo #
--echo # Bug#34080394: Hypergraph Offload issue : Problem in
--echo # ExtractRequiredItemsForFilter.
--echo #
CREATE TABLE t1 (f1 YEAR);
EXPLAIN FORMAT=tree SELECT * FROM t1 WHERE f1 = 1 AND f1 <> 11;
DROP TABLE t1;
--echo #
--echo # Bug#34504697: Hypergraph: Assertion
--echo # `!(used_tabs & (~read_tables & ~filter_for_table))'
--echo # failed
--echo #
CREATE TABLE t1 (f1 INTEGER);
SELECT 1
FROM t1 LEFT JOIN (SELECT t2.*
FROM (t1 AS t2 INNER JOIN t1 AS t3 ON (t3.f1 = t2.f1))
WHERE (t3.f1 <> 1 OR t2.f1 > t2.f1)) AS dt
ON (t1.f1 = dt.f1);
DROP TABLE t1;
--echo #
--echo # Bug#34503695:Hypergraph: mysqld crash-signal 11
--echo # -CommonSubexpressionElimination
--echo #
CREATE TABLE t1 (f1 INTEGER);
# For the NOT IN subquery, hypergraph does re-planning with materialization.
# This replanning uses the modified where condition from the previous planning.
# For this case, the where condition is concluded as always false resulting in
# removal of elements from the OR condition leading to a crash during re-planning.
# The modified where condition from the first planning should not affect AND/OR
# structure of the condition.
SELECT * FROM t1
WHERE t1.f1 NOT IN (SELECT t2.f1
FROM (t1 AS t2 JOIN t1 AS t3 ON (t3.f1 = t2.f1))
WHERE (t3.f1 <> t2.f1 OR t3.f1 < t2.f1));
DROP TABLE t1;
--echo #
--echo # Bug#34527126: Some rapid tests in MTR fail with hypergraph
--echo # when run in --ps-protocol mode
--echo #
CREATE TABLE t1(f1 INTEGER);
# The error generated during planning for the first derived query block
# should not result in an assert failure when the second derived table is
# cleaned up.
PREPARE ps FROM
"SELECT * FROM (WITH RECURSIVE qn AS (SELECT 1 FROM t1 UNION ALL
SELECT 1 FROM t1 STRAIGHT_JOIN qn)
SELECT * FROM qn) AS dt1,
(SELECT COUNT(*) FROM t1) AS dt2";
--error ER_CTE_RECURSIVE_FORBIDDEN_JOIN_ORDER
EXECUTE ps;
DROP TABLE t1;
--echo #
--echo # Bug#34494877: WL#14449: Offload issue: RapidException (3):
--echo # rpdrqctr_transcode.c:1447 @ rpdoqc_
--echo #
CREATE TABLE t(x INT, y INT);
INSERT INTO t VALUES (1, 10), (2, 20), (3, 30);
ANALYZE TABLE t;
# Expect the entire query to be optimized away. It used to produce a
# join between t and a temporary table containing the result of a
# "Zero rows" plan.
let $query =
SELECT * FROM
t RIGHT JOIN
(SELECT MAX(y) AS m FROM t WHERE FALSE GROUP BY x) AS dt
ON t.x = dt.m;
--eval EXPLAIN FORMAT=TREE $query
--eval $query
# Similar to the above, but the query cannot be entirely optimized
# away, since the outer table isn't empty. It used to add a
# materialization step on top of the zero rows plan for the derived
# table. Now it should just have zero rows directly on the inner side
# of the join.
let $query =
SELECT * FROM
t LEFT JOIN
(SELECT MAX(y) AS m FROM t WHERE FALSE GROUP BY x) AS dt
ON t.x = dt.m;
--replace_regex $elide_costs
--eval EXPLAIN FORMAT=TREE $query
--eval $query
# Similar case, where the query cannot be entirely optimized away.
# Verify that the entire inner side of the outer join is optimized
# away. Only t1 should be accessed.
let $query =
SELECT * FROM
t AS t1 LEFT JOIN
(t AS t2
INNER JOIN (SELECT MAX(y) AS m FROM t WHERE FALSE GROUP BY x) AS dt
ON t2.x = dt.m)
ON t1.x = t2.y;
--replace_regex $elide_costs
--eval EXPLAIN FORMAT=TREE $query
--eval $query
DROP TABLE t;
--echo #
--echo # Bug#34534373: Heatwave offload issue - Sees inner tables of
--echo # a semijoin when it should not
--echo #
CREATE TABLE t1 (f1 INTEGER);
# The condition t2.f1 = t3.f1+1 should be placed as a join condition
# for the semijoin and not on the outer join.
--replace_regex $elide_costs
EXPLAIN FORMAT=tree
SELECT 1
FROM t1 LEFT JOIN (SELECT * FROM t1 AS t2
WHERE f1 IN (SELECT f1+1 FROM t1 AS t3)) AS dt
ON t1.f1=dt.f1;
DROP TABLE t1;
--echo #
--echo # Bug#34699398: Row estimates for joins ignores histograms.
--echo #
CREATE TABLE num (n INT);
INSERT INTO num VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
CREATE TABLE t1 (a INT, ah INT, ai INT, KEY ix1(ai));
INSERT INTO t1 SELECT k%25, k%25, K%25 FROM
(SELECT num1.n+num2.n*10 k FROM num num1, num num2) d1;
CREATE TABLE t2 (b INT, bh INT, bi INT, KEY ix2(bi));
INSERT INTO t2 SELECT k%25, k%25, k%25 FROM
(SELECT num1.n+num2.n*10 k FROM num num1, num num2, num num3) d1;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON ah;
ANALYZE TABLE t2 UPDATE HISTOGRAM ON bh;
ANALYZE TABLE t1,t2;
# Neither index nor histogram, so use 10% selectivity estimate.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1,t2 WHERE a=b;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 x1, t1 x2 WHERE x1.a=x2.a;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t2 x1, t2 x2 WHERE x1.b=x2.b;
# Estimate selectivity from ix1.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1,t2 WHERE ai=b;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 x1, t1 x2 WHERE x1.ai=x2.ai;
# Estimate selectivity from ix1 or ix2.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1,t2 WHERE ai=bi;
# Estimate selectivity from ix2.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1,t2 WHERE a=bi;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t2 x1, t2 x2 WHERE x1.bi=x2.bi;
# Estimate selectivity from histogram on 'a'.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1,t2 WHERE ah=b;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 x1, t1 x2 WHERE x1.ah=x2.ah;
# Estimate selectivity from histogram on 'a' or 'b'.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1,t2 WHERE ah=bh;
# Estimate selectivity from histogram on 'b'.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1,t2 WHERE a=bh;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t2 x1, t2 x2 WHERE x1.bh=x2.bh;
DROP TABLE num, t1, t2;
--echo #
--echo # Bug#34682561: Assertion `!eq_items.is_empty()' failed
--echo # in make_join_hypergraph.cc
--echo #
CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
ANALYZE TABLE t1;
let $query =
SELECT f1 FROM t1
WHERE EXISTS (SELECT t2.f1
FROM (t1 AS t2 JOIN t1 AS t3 ON (t3.f1 = t2.f2))
LEFT JOIN t1 AS t4 ON TRUE
WHERE t4.f1 = t3.f1 OR t3.f2 >= t2.f2)
GROUP BY f1;
--replace_regex $elide_costs
eval EXPLAIN FORMAT=tree $query;
eval $query;
DROP TABLE t1;
--echo #
--echo # Bug#34717171: Hypergraph :Assertion `false' failed
--echo # in join_optimizer.cc
--echo #
CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, x INT);
CREATE TABLE t2 (x INT);
INSERT INTO t1 VALUES (), (), (), (), (), (), (), (), (), ();
INSERT INTO t2 VALUES (), (), (), (), (), (), (), (), (), ();
ANALYZE TABLE t1,t2;
let $query =
WITH subq AS (
SELECT * FROM t2
WHERE x IN (SELECT t1.pk FROM t1, t2 AS t3 WHERE t1.x = t3.x)
)
SELECT 1 FROM subq LEFT JOIN t2 AS t4 ON TRUE WHERE subq.x = t4.x;
--replace_regex $elide_costs
eval EXPLAIN FORMAT=tree $query;
eval $query;
DROP TABLE t1,t2;
--echo #
--echo # Bug#34828364: Assertion `!eq_items.is_empty()' failed
--echo # in make_join_hypergraph.cc
--echo #
CREATE TABLE t1 (f1 INTEGER, f2 INTEGER);
ANALYZE TABLE t1;
let $query =
SELECT 1
FROM (SELECT * FROM t1
WHERE f1 IN (SELECT t1.f1 FROM (t1 AS t2 JOIN t1 AS t3 ON t3.f1 = t2.f2)
LEFT JOIN t1 AS t4 ON TRUE
WHERE (t3.f2 <> t3.f2 OR t4.f2 = t2.f2))) AS t5 JOIN t1 AS t6
ON TRUE;
--replace_regex $elide_costs
eval EXPLAIN FORMAT=tree $query;
eval $query;
DROP TABLE t1;
--echo #
--echo # Bug#34821222: Hypergraph: mysqld crash-signal 11 - IsAnd &
--echo # CommonSubexpressionElimination
--echo #
CREATE TABLE t1 (x INTEGER NOT NULL);
CREATE TABLE t2 (y INTEGER, z INTEGER);
SELECT 1 IN (
SELECT COUNT(*) FROM t1 WHERE x NOT IN (
SELECT 1 FROM t2 WHERE y <> y OR z <> z));
DROP TABLE t1, t2;
--echo #
--echo # Bug#34854369: Customer query hits assert(m_pq.is_valid()) failure
--echo #
# Graph simplification used to hit an assertion as a result of
# division by zero caused by information schema tables with zero row
# estimates.
CREATE TABLE t (table_id BIGINT UNSIGNED);
SELECT /*+ SET_VAR(optimizer_max_subgraph_pairs = 1) */ 1
FROM t AS t1 JOIN t AS t2 USING (table_id)
JOIN INFORMATION_SCHEMA.INNODB_TABLES AS t3 USING (table_id)
JOIN INFORMATION_SCHEMA.INNODB_TABLES AS t4 USING (table_id)
JOIN INFORMATION_SCHEMA.INNODB_TABLES AS t5 USING (table_id)
JOIN INFORMATION_SCHEMA.INNODB_TABLES AS t6 USING (table_id)
JOIN INFORMATION_SCHEMA.INNODB_TABLES AS t7 USING (table_id)
JOIN INFORMATION_SCHEMA.INNODB_TABLES AS t8 USING (table_id);
DROP TABLE t;
# Graph simplification used to hit an assertion as a result of
# division by zero caused by zero row estimates from MyISAM. (InnoDB
# never gives zero row estimates, not even for empty tables, whereas
# MyISAM does.)
CREATE TABLE t0 (x INT) ENGINE = MyISAM;
CREATE TABLE t1 (x INT) ENGINE = InnoDB;
SELECT /*+ SET_VAR(optimizer_max_subgraph_pairs = 1) */ 1
FROM t0 AS a NATURAL JOIN
t0 AS b NATURAL JOIN
t0 AS c NATURAL JOIN
t0 AS d NATURAL JOIN
t0 AS e NATURAL JOIN
t0 AS f NATURAL JOIN
t1 AS g NATURAL JOIN
t1 AS h;
DROP TABLE t0, t1;
--echo #
--echo # Bug#34861693: Assertion
--echo # `std::abs(1.0 - EstimateAggregateRows(child, query_block, path->aggreg
--echo #
CREATE TABLE num (n INT);
INSERT INTO num VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
CREATE TABLE t1 (a INT, b INT);
INSERT INTO t1 SELECT n,n FROM num UNION SELECT n+10,n+10 FROM num;
CREATE TABLE t2 (a INT, b INT);
ANALYZE TABLE t1, t2;
# The row estimate for "x1 LEFT JOIN (x2 LEFT JOIN x3)" may be different from that of
# "(x1 LEFT JOIN x2) LEFT JOIN x3" (see bug #33550360 "Inconsistent row estimates
# in the hypergraph optimizer"). Then the the row estimate for GROUP BY will also depend
# on the join order. This triggers the assert (i.e. bug#34861693).
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT x1.a+0 k, COUNT(x1.b) FROM t1 x1
LEFT JOIN t2 x2 ON x1.b=x2.a
LEFT JOIN t1 x3 ON x2.b=x3.a GROUP BY k;
DROP TABLE t1,t2,num;
--echo #
--echo # Bug#35000554: assertion error in EstimateAggregateNoRollupRows()
--echo #
CREATE TABLE num10 (n INT);
INSERT INTO num10 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
CREATE TABLE t1(a INT, b INT, c INT);
ANALYZE TABLE t1 UPDATE HISTOGRAM ON a, b, c;
INSERT INTO t1 SELECT NULL, x1.n+x2.n*10, NULL FROM num10 x1, num10 x2;
INSERT INTO t1 VALUES (NULL, 0, 0);
ANALYZE TABLE t1;
# Row estimate should not be zero, even if histogram was built on empty table.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT b FROM t1 GROUP BY b;
# Row estimate should not be zero, even if histogram was built on empty table.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT b FROM t1 WHERE b=c;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON a, b, c;
# Prior to the fix, this would trigger the assert, as we would estimate
# zero distinct values for 'a'.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT a,b FROM t1 GROUP BY a,b;
# Now there is an updated histogram (built on a non-empty table),
# and thus a better estimate.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT b FROM t1 WHERE b=c;
# Estimate should be two rows (NULL and 0).
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT c FROM t1 GROUP BY c;
DROP TABLE num10, t1;
CREATE TABLE t2(a INT, b INT);
INSERT INTO t2 VALUES (0, 0), (0, 1), (1, 2), (NULL, 3), (NULL, 4), (NULL, 5);
ANALYZE TABLE t2 UPDATE HISTOGRAM ON a, b;
ANALYZE TABLE t2;
# Estimate should be 1.5 rows (i.e. 25% of the table), as there are two distinct
# values, and 'a' is NULL for 50% of the rows.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t2 WHERE a=b;
DROP TABLE t2;
--echo #
--echo # Bug#35129863 Hypergraph: Multi-field indexes ignored in some
--echo # selectivity estimates
--echo #
CREATE TABLE num10 (n INT PRIMARY KEY);
INSERT INTO num10 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
CREATE TABLE t1(
a INT,
b INT,
c INT,
d INT,
e INT,
f INT,
g INT,
h INT,
v VARCHAR(5),
PRIMARY KEY(a,b,c),
KEY k1 (e,f,g),
UNIQUE KEY k2(h)
);
INSERT INTO t1
SELECT k%25, k%50, k, k, k%25, k%50, k, k, CAST( k%25 AS CHAR(5))
FROM (select x1.n*10+x2.n k from num10 x1, num10 x2) d1;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON a, b,c,d,e,f,g,v;
ANALYZE TABLE t1;
# Since [a,b] is a prefix of the primary key, we use the selectivity of this prefix instead
# of multiplying individual sekectivities of each field.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2 WHERE x1.a=x2.a AND x1.b=x2.b;
# [a,b,c] is also a prefix of the primary key.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2, t1 x3
WHERE x1.a=x2.a AND x1.b=x2.b AND x2.c=x3.c AND x2.d=x3.d;
# Prefix of k1.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2 WHERE x1.e=x2.e AND x1.f=x2.f;
# Prefix of k1.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2 WHERE x1.e=x2.e AND x1.f=x2.f AND x1.g=x2.g;
# 'a' and 'e' are prefixes of two separate keys, so we multiply the selectivity of each.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2 WHERE x1.a=x2.a AND x1.e=x2.e;
# [a,b] and [e,f] are index prefixes. Multiply the selectivity of each prefix.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2 WHERE x1.a=x2.a AND x1.b=x2.b
AND x1.e=x2.e AND x1.f=x2.f;
# [x2.a, x2.b] form an index prefix, but they are joined with different tables
# (x1 and x3). Therefore we derive the selectivity for x2.a from the
# primary key, and the selectivty of x2.b from the histogram for that field.
# And then we multiply these selectivities.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2, t1 x3 WHERE x1.a=x2.a AND x2.b=x3.b;
# Mix of field=field and field=constant
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2 WHERE x1.a=x2.a AND x1.b=8;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2 WHERE x1.a=x2.a AND x1.b=x2.b
AND x1.c=8;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2 WHERE x1.a=x2.a AND x1.b=7
AND x1.c=8;
# Join on entire primary key.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2 WHERE x1.a=x2.a AND x1.b=x2.b
AND x1.c=x2.c;
# field=field on single table.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 WHERE a=b;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 WHERE a=b AND c=d;
# Cycle x1->x2->x3 in predicate.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE FORMAT=TREE SELECT * FROM t1 x1, t1 x2, t1 x3
WHERE x1.a=x2.a AND x2.b=x3.b AND x3.c=x1.c;
# Cap on most selective unique key (k2).
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 JOIN num10 ON h=n;
# Cap on unique key k2 takes priority over [t1.a,t1.b] index prefix.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2, t1 x3 WHERE
x1.a=x2.a AND x1.b=x2.b AND x1.b=x3.h;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1, t1 x2, t1 x3
WHERE x1.a=x2.c AND x1.b=x2.b AND x2.b=x3.b;
# x3.a is missing on the inner side of the left join. Therefore we use
# histograms rather than the [x3.a, x3.b] index prefix for finding the
# selectivity of x3.b=x1.d.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 x1 LEFT JOIN
(t1 x2 JOIN t1 x3 ON x2.a=x3.a AND x2.b=x3.b) ON x3.b=x1.d;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 x1
WHERE 3 IN (SELECT x2.b FROM t1 x2 LEFT JOIN t1 x3 ON x2.c=x3.a AND x2.d=x3.b);
# Implicit cast from VARCHAR to INT.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 x1 JOIN t1 x2 ON x1.a=x2.v AND x1.b=x2.b;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 x1, t1 x2, t1 x3
WHERE x1.a=x2.c AND x1.a=x3.v AND x1.b=x3.f;
CREATE TABLE t2(x INT, y INT, z INT, KEY (x, y), KEY(y, x));
INSERT INTO t2(x, y) VALUES (1, 1), (2, 2), (3, 3), (4, 4);
CREATE TABLE t3 AS SELECT * FROM t2;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t2 JOIN t3 USING (x, y);
ANALYZE TABLE t2,t3;
DROP TABLE t1, t2, t3, num10;
--echo #
--echo # Bug#34762651 Too high row estimates for DISTINCT
--echo #
CREATE TABLE t1(
a INT PRIMARY KEY,
b INT,
KEY(b),
c INT
);
INSERT INTO t1
WITH RECURSIVE qn(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM qn WHERE n<100)
SELECT n, n%5, n%7 FROM qn;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON c;
ANALYZE TABLE t1;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT DISTINCT b FROM t1;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT DISTINCT c FROM t1;
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT DISTINCT b,c FROM t1;
DROP TABLE t1;
--echo #
--echo # Bug#34763224 Hypergraph orders and-terms inefficiently in subquery
--echo #
CREATE TABLE num (n INT);
INSERT INTO num VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
CREATE TABLE t1(
a INT PRIMARY KEY,
b VARCHAR(128),
c INT
);
INSERT INTO t1 SELECT k, CAST(100+k AS CHAR(10)), k
FROM (SELECT x1.n+x2.n*10 AS k FROM num x1, num x2) d1;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON b, c;
ANALYZE TABLE t1;
# 'c<70' is cheaper even if it is less selective, so evaluate that first.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT 1 FROM t1 x1 WHERE x1.c IN
(SELECT c FROM t1 x2 WHERE b<"150" AND c<70);
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT 1 FROM t1 WHERE b<"150" AND c<70;
# Even if 'c<80' is cheaper, its selectivity is so low that it should be
# evaluated last.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT 1 FROM t1 WHERE b<"150" AND c<80;
--echo #
--echo # BUG 35507456
--echo # Assertion `[&]() { for (const Predicate *first = begin; first < end; first++)
--echo #
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT 1 FROM t1
WHERE b<"150" AND RAND(0)>-1 AND c< 70;
DELIMITER $$;
CREATE FUNCTION foo(i INT)
RETURNS INT
LANGUAGE SQL
BEGIN
RETURN i+1;
END $$
DELIMITER ;$$
# Function call should be evaluated last.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT 1 FROM t1 WHERE foo(2)=3 AND c=5;
DROP FUNCTION foo;
DROP TABLE num, t1;
--echo #
--echo # Bug#34787357 Hypergraph: row estimates for field=non_field_term
--echo # ignores indexes and histogram
--echo #
CREATE TABLE t1 (
a INT,
b INT,
c INT,
d INT,
e INT,
f INT,
g INT,
PRIMARY KEY(a),
KEY k1 (b,d), -- 'b' and 'd' are indepdendent.
KEY k2 (b,e), -- 'b' is funtionally dependent on 'e'.
KEY k3 (b,g), -- 'b' is funtionally dependent on 'g'.
KEY k4 (f,g) -- 'f' and 'g' are independet.
);
INSERT INTO t1
WITH RECURSIVE qn(n) AS
(SELECT 0 UNION ALL SELECT n+1 FROM qn WHERE n<255)
SELECT n AS a, n DIV 16 AS b, n % 16 AS c, n % 16 AS d, n DIV 8 AS e,
n % 32 AS f, n DIV 8 AS g FROM qn;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON c;
ANALYZE TABLE t1;
# We estimate selectivity of <field>=<independent expression> as
# 1/<num distinct values of field>. If there is a histogram on <field>,
# or if it is the first field of an (non-hash) index, then the (estimated)
# number of distinct values is directly available. If it is the second or
# subsequent field of an index, we do not know to what extent <field> is
# correlated with the preceeding fields. In this case, we estimate the
# selectivity as the geometric mean of the two extermes:
# 1) Uncorrelated:
# selectivity = records_per_key(prefix+key) / rows_in_table
#
# 2) prefix is functionally dependent on field:
# selectivity = records_per_key(prefix+key) / records_per_key(prefix)
# Make estimate from index, even if value is unknown.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE b=FLOOR(RAND(0));
# Make estimate from histogram, even if value is unknown.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE c=FLOOR(RAND(0));
# Make estimate from histogram, even if value is unknown. Note that the field
# is on the right hand side of '='.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE FLOOR(RAND(0))=c;
# Make estimate from second field of index. Since 'b' and 'd' are independent,
# the estimate will be too low.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE d=FLOOR(RAND(0));
# Make estimate from second field of index. Since 'b' in functionally dependent
# on 'e', the estimate will be too high.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE e=FLOOR(RAND(0));
# Make estimate from second field of index. Since 'b' and 'd' are independent,
# the estimate will be too low.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE d=0;
# Make estimate from second field of index. Since 'b' in functionally dependent
# on 'e', the estimate will be too high.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE e=0;
# Make estimate from second field of indexes k3 and k4.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE g=FLOOR(RAND(0));
# Make estimate from index, even if value is unknown.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE b=(SELECT MIN(b) FROM t1);
# Make estimate from histogram, even if value is unknown.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE c=(SELECT MIN(b) FROM t1);
# Use histogram or index to make estimate for <field>!=<expression>
# predicates.
# Make estimate from index, even if value is unknown.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE b<>FLOOR(RAND(0));
# Make estimate from histogram, even if value is unknown.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE c<>FLOOR(RAND(0));
# Make estimate from histogram, even if value is unknown. Note that the field
# is on the right hand side of '<>'.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE FLOOR(RAND(0))<>c;
# Make estimate from index, even if value is unknown.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE b<>(SELECT MIN(b) FROM t1);
# Make estimate from histogram, even if value is unknown.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE c<>(SELECT MIN(b) FROM t1);
# Make estimate from second field of index.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE d<>(SELECT MIN(b) FROM t1);
# Make estimate from second field of index.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT 1 FROM t1 WHERE e<>(SELECT MIN(b) FROM t1);
# Subquery with column resolved in outer reference (OUTER_REF_TABLE_BIT).
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE FORMAT=TREE SELECT * FROM t1 x1 WHERE d =
(SELECT MIN(g) FROM t1 x2 WHERE x1.b<>x2.b);
DROP TABLE t1;
--echo # Bug#35439787 Assertion `false && "Inconsistent row counts for
--echo # different AccessPath objects."'
--echo #
CREATE TABLE t1 (
a INT PRIMARY KEY,
b INT,
c INT,
d INT,
e INT,
KEY k1 (b,c)
);
ANALYZE TABLE t1;
# To reproduce this bug we use a query with:
# - A top-level semi-join, so that we get one CompanionSet for the
# root and one for the inner-join.
# - A cyclic dependency between x2, x3 and x4.
# - Terms comparing both the first and second field in a key to
# other fields.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT 1 FROM t1 x1 WHERE EXISTS
(SELECT 1 FROM t1 x2, t1 x3, t1 x4
WHERE x2.b=x3.d AND x2.c=x3.e AND x3.d=x4.b AND x2.e=x4.e);
DROP TABLE t1;
# Test case for post-push fix for commit with
# 'Change-Id: I40156663f32a407490b066a566abe72b356cfda9'. Fix for UBSAN
# error: building reference to dereferenced null pointer.
CREATE TABLE t1 (a int, b int);
ANALYZE TABLE t1;
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 x1 LEFT JOIN (t1 x2, t1 x3)
ON x1.a=x3.a WHERE x1.b<x2.b OR x2.a IS NULL;
DROP TABLE t1;
--echo #
--echo # Bug#35719688 Assertion`new_path->cost >= new_path->init_cost' in
--echo # ExpandSingleFilterAccessPath
--echo #
CREATE TABLE t1 (
a INT,
b INT,
c INT,
PRIMARY KEY(a),
KEY k_b(b),
KEY k_c(c)
);
INSERT INTO t1 VALUES (1,1,1);
ANALYZE TABLE t1;
CREATE TABLE t2 (
a INT PRIMARY KEY,
b INT
);
INSERT INTO t2 WITH RECURSIVE qn(n) AS
(SELECT 1 UNION ALL SELECT n+1 FROM qn WHERE n<50) SELECT n, n FROM qn;
ANALYZE TABLE t2;
# To trigger this bug we need a query with:
# - A ROWID_UNION access path.
# - A predicate giving a selectivity estmate of zero (prior to the fix).
# - An expensive filter condition.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 x0 WHERE (b=3 OR c=4) AND a <>
(SELECT MAX(x1.a+x2.a) FROM t2 x1 JOIN t2 x2 ON x1.b<x2.b);
DROP TABLE t1,t2;
--echo #
--echo # Bug#35789967 Assertion `val >= 0.0 || val == kUnknownCost' failed.
--echo #
CREATE TABLE t1
(
a INT,
b INT,
c INT,
PRIMARY KEY(a),
KEY k2 (b,c)
);
INSERT INTO t1
WITH RECURSIVE qn(n) AS (SELECT 10 UNION ALL SELECT n-1 FROM qn WHERE n>0)
SELECT n, 1, n FROM qn;
ANALYZE TABLE t1;
# The assert was triggered by an independent singlerow subselect as a filter
# condition.
--replace_regex $elide_costs_and_rows
EXPLAIN FORMAT=TREE SELECT b FROM t1 x1
WHERE c < 1 AND c = (SELECT MAX(b) FROM t1 x2);
DROP TABLE t1;
--echo #
--echo # Bug#35790381 Assertion `false &&
--echo # "Inconsistent row counts for different AccessPath objects."'
--echo #
CREATE TABLE t1 (a INT, b INT, KEY k1 (a));
INSERT INTO t1 VALUES (1,1),(2,2),(1,1),(2,2),(1,1),(2,2),(1,1),(2,2),(1,1),(2,2),(1,1),(2,2);
ANALYZE TABLE t1 UPDATE HISTOGRAM ON b;
ANALYZE TABLE t1;
# The code that made row estimates for aggregation did not understand that
# 'a' was a field, since it was represented by an Item_ref rather than an
# Item_field. Therefore, it ignored the k1 index, and used a rule of thumb
# instead (the square root of the number of input rows).
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT a, COUNT(*) FROM
(SELECT x1.a FROM t1 x1, t1 x2 WHERE x1.b = x2.a) AS dt GROUP BY a;
DROP TABLE t1;
--echo #
--echo # Bug#35483044 Hypergraph: Invalid row estimate for filter on
--echo # 'Index range scan'
--echo #
CREATE TABLE t1 (
a INT PRIMARY KEY,
b INT NOT NULL,
c INT,
KEY k_b(b),
KEY k_c(c)
);
INSERT INTO t1 WITH RECURSIVE qn(n) AS
(SELECT 1 UNION ALL SELECT n+1 FROM qn WHERE n<30) SELECT n, n/2, n/2 FROM qn;
ANALYZE TABLE t1;
# c=NULL is always false and should not affect the row estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b=5 OR c=NULL;
# 'c<=>NULL' and 'c IS NULL' are equivalent and should get the same row
# estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b=5 OR c<=>NULL;
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b=5 OR c IS NULL;
# b=NULL is always false and should not affect the row estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b=NULL OR c=5;
# b<=>NULL is always false and should not affect the row estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b<=>NULL OR c=5;
# Use index for selectivity estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b<=>FLOOR(RAND(0));
# Use index for selectivity estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE c<=>FLOOR(RAND(0));
ANALYZE TABLE t1 UPDATE HISTOGRAM ON b,c;
# c=NULL is always false and should not affect the row estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b=5 OR c=NULL;
# 'c<=>NULL' and 'c IS NULL' are equivalent and should get the same row
# estimate (from the histogram).
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b=5 OR c<=>NULL;
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b=5 OR c IS NULL;
# b=NULL is always false and should not affect the row estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b=NULL OR c=5;
# b<=>NULL is always false and should not affect the row estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b<=>NULL OR c=5;
# Use index for selectivity estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE b<=>FLOOR(RAND(0));
# Use index for selectivity estimate.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE c<=>FLOOR(RAND(0));
DROP TABLE t1;
--echo #
--echo # Bug#35898221 Hypergraph: too low row estmate for semijoin
--echo # that is not an equijoin
--echo #
CREATE TABLE t1 (
a INT PRIMARY KEY,
b INT
);
CREATE TABLE t2 (
k INT,
l INT,
PRIMARY KEY(k)
);
INSERT INTO t1 WITH RECURSIVE qn(n) AS
(SELECT 0 UNION ALL SELECT n+1 FROM qn WHERE n<29) SELECT n, n FROM qn;
INSERT INTO t2 WITH RECURSIVE qn(n) AS
(SELECT 0 UNION ALL SELECT n+1 FROM qn WHERE n<19) SELECT n, n%10 FROM qn;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON b;
ANALYZE TABLE t2 UPDATE HISTOGRAM ON l;
ANALYZE TABLE t1,t2;
# Simple semijoin. The row estimate should be:
# CARD(t1) * CARD("SELECT DISTINCT l FROM t2") * SELECTIVITY(t1.a=t2.l)
# = 30 * 10 * 1/30 = 10.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 WHERE t1.a IN (SELECT t2.l FROM t2);
# Semijoin that is not an equijoin.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 WHERE EXISTS
(SELECT 1 FROM t2 WHERE t1.a=t2.l AND t1.b<>t2.k);
# Semijoin refering same inner field ('l') multiple times.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 WHERE EXISTS
(SELECT 1 FROM t2 WHERE t2.l+ABS(t2.l)=t1.a);
# Semijoin refering multiple inner fields.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 WHERE EXISTS
(SELECT 1 FROM t2 WHERE t2.k+t2.l=t1.a);
# Simple antijoin.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 WHERE NOT EXISTS
(SELECT 1 FROM t2 WHERE t1.a=t2.l);
# Antijoin that is not an equijoin.
--replace_regex $elide_costs_and_time
EXPLAIN ANALYZE SELECT * FROM t1 WHERE NOT EXISTS
(SELECT 1 FROM t2 WHERE t1.a=t2.l AND t1.b<>t2.k);
# Semijoin with row estimate from inner operand less than one.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE a IN
(SELECT t2.l FROM t2 WHERE t2.l<0);
# Semijoin with constant inner operand.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE t1.a IN (SELECT 5 FROM t2);
DROP TABLE t1,t2;
--echo #
--echo # Bug#35997316 Hypergraph: Incomplete and inconvenient optimizer trace
--echo #
CREATE TABLE t1 (a INT PRIMARY KEY, b INT);
INSERT INTO t1 WITH RECURSIVE qn(n) AS
(SELECT 0 UNION ALL SELECT n+1 FROM qn WHERE n+1<30) SELECT n, n%10 FROM qn;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON b;
ANALYZE TABLE t1;
SET SESSION OPTIMIZER_TRACE='enabled=on';
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 x1
WHERE x1.a IN (SELECT x2.b FROM t1 x2);
# Check that how we estimate the number of distinct values for x2.b are
# logged in the optimizer trace.
SELECT REGEXP_SUBSTR(
trace, "distinct values for field 'b' from histogram[^,]*",1,1,'n')
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SET SESSION OPTIMIZER_TRACE='enabled=off';
DROP TABLE t1;
--echo #
--echo # Bug#36125903 Hypergraph: Inconsistent numeric precision for
--echo # AccessPath in optimizer trace
--echo #
CREATE TABLE t1 (
a INT PRIMARY KEY,
b INT
);
INSERT INTO t1 WITH RECURSIVE qn(n) AS
(SELECT 0 UNION ALL SELECT n+1 FROM qn WHERE n<100) SELECT n, n FROM qn;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON b;
ANALYZE TABLE t1;
SET SESSION OPTIMIZER_TRACE="enabled=on";
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 x1, t1 x2, t1 x3, t1 x4;
SELECT REGEXP_SUBSTR(trace, " - \\{NESTED_LOOP_JOIN[^\n]*keeping",1,1,'n')
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 WHERE a=5 AND b=5;
SELECT REGEXP_SUBSTR(trace, " - \\{FILTER[^\n]*keeping",1,1,'n')
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SET SESSION OPTIMIZER_TRACE="enabled=off";
DROP TABLE t1;
--echo # Bug#5889990: Setting secondary_engine to OFF causes offload issues
CREATE TABLE t(x INT, y INT);
INSERT INTO t VALUES (1, 2), (2, 3);
ANALYZE TABLE t;
SET optimizer_switch='hypergraph_optimizer=off';
PREPARE ps FROM
'SELECT *
FROM t AS t1 LEFT JOIN t AS t2 ON t1.x=t2.x AND t1.y IN (SELECT x FROM t)';
EXECUTE ps;
SET optimizer_switch='hypergraph_optimizer=on';
EXECUTE ps;
SET optimizer_switch='hypergraph_optimizer=off';
EXECUTE ps;
SET optimizer_switch='hypergraph_optimizer=on';
PREPARE ps FROM
'SELECT *
FROM t AS t1 LEFT JOIN t AS t2 ON t1.x=t2.x AND t1.y IN (SELECT x FROM t)';
EXECUTE ps;
SET optimizer_switch='hypergraph_optimizer=off';
EXECUTE ps;
DROP TABLE t;
CREATE TABLE t(x VARCHAR(100), FULLTEXT KEY (x));
INSERT INTO t VALUES ('abc'), ('xyz'), ('abc abc');
ANALYZE TABLE t;
SET optimizer_switch='hypergraph_optimizer=on';
PREPARE ps FROM
'SELECT x, MATCH(x) AGAINST (''abc'') AS score FROM t
GROUP BY x HAVING MATCH(x) AGAINST(''abc'') > 0';
EXECUTE ps;
SET optimizer_switch='hypergraph_optimizer=off';
EXECUTE ps;
SET optimizer_switch='hypergraph_optimizer=on';
EXECUTE ps;
SET optimizer_switch='hypergraph_optimizer=off';
PREPARE ps FROM
'SELECT x, MATCH(x) AGAINST (''abc'') AS score FROM t
GROUP BY x HAVING MATCH(x) AGAINST(''abc'') > 0';
EXECUTE ps;
SET optimizer_switch='hypergraph_optimizer=on';
EXECUTE ps;
DROP TABLE t;
--echo #
--echo # Bug #36135001: Hypergraph: Too low row estimate for index lookup
--echo #
CREATE TABLE t1(
a INT,
b INT,
c INT,
d INT,
PRIMARY KEY(a),
KEY k1(d)
);
INSERT INTO t1
WITH RECURSIVE qn(n) AS
(SELECT 0 UNION ALL SELECT n+1 FROM qn WHERE n<19)
SELECT n, n%10, n%10, n%10 FROM qn;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON b,c;
ANALYZE TABLE t1;
# Do a lookup on the primary key, so that we can verify that the row estimate
# is 1.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 x1, t1 x2, t1 x3
WHERE x1.b=x2.a AND x2.b=x3.a AND (x1.c < 5 OR x3.c=7);
# Do a lookup on non-unique key k1, where the row estimate should be 2.
# 'ORDER BY' ensures that we get a nested loop join, where the lookup is
# present.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 x1, t1 x2, t1 x3
WHERE x1.b=x2.d AND x2.b=x3.d AND (x1.c < 5 OR x3.c=7) ORDER BY x3.d;
# Check that we handle two identical conditions correctly.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT * FROM t1 x1 LEFT JOIN t1 x2
ON x1.a <=> x2.a AND x1.a <=> x2.a;
DROP TABLE t1;
--echo #
--echo # Bug#35855573 Assertion `false && "Inconsistent row counts for
--echo # different AccessPath objects."'
--echo #
CREATE TABLE t(pk INT PRIMARY KEY AUTO_INCREMENT, x INT);
INSERT INTO t VALUES (), (), (), (), (), (), (), (), (), (), (), ();
ANALYZE TABLE t;
# Since t1.pk = t2.x and pk is the primary key, there is a functional
# dependency t2.x->t1.x. Therefore, some candidate plans group on {t2.x, t1.x}
# and others on {t1.x}, which are both valid. But EstimateDistinctRows() will
# give different row estimates for these two sets of fields, as it does not take
# functional depdenencies into account. This triggered the assert.
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT DISTINCT t1.x, t2.x FROM t AS t1, t AS t2
WHERE t1.pk = t2.x ORDER BY t2.x;
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT DISTINCT t1.x, t1.pk FROM t AS t1, t AS t2
WHERE t1.pk = t2.x ORDER BY t1.x;
--replace_regex $elide_costs
EXPLAIN FORMAT=TREE SELECT DISTINCT t1.pk, t2.x FROM t AS t1, t AS t2
WHERE t1.pk = t2.x ORDER BY t2.x;
DROP TABLE t;
--echo #
--echo # Bug#35991881 Hypergraph: Wrong init_cost for nested loop join
--echo #
CREATE TABLE t1 (
a INT PRIMARY KEY,
b INT,
c INT
);
INSERT INTO t1 WITH RECURSIVE qn(n) AS
(SELECT 0 UNION ALL SELECT n+1 FROM qn WHERE n+1<20)
SELECT n, n%10, n%10 FROM qn;
ANALYZE TABLE t1 UPDATE HISTOGRAM ON b, c;
ANALYZE TABLE t1;
# This query should produce a plan with a NLJ between x1 and d1, since we
# order on an indexed column (x1.a) and have LIMIT.
# The relatively high first-row cost for d1 should be included in the
# first-row cost of that NLJ.
EXPLAIN FORMAT=TREE SELECT * FROM t1 x1 JOIN
(SELECT MAX(x2.c) k FROM t1 x2 JOIN t1 x3 ON x2.c < x3.b GROUP BY x3.c) d1
ON x1.b=d1.k ORDER BY x1.a LIMIT 1;
DROP TABLE t1;
--echo #
--echo # Bug#36032958: Assertion `IsEmpty(child.delayed_predicates)' failed
--echo #
CREATE TABLE t(x INT, KEY(x));
SELECT ROW_NUMBER() OVER () FROM t WHERE x = RAND() GROUP BY x;
DROP TABLE t;
--echo #
--echo # Bug#36099491: Assertion secondary_engine_cost_hook != nullptr
--echo # failed with hypergraph_optimizer
--echo #
CREATE TABLE t (a INT, b VARCHAR(10));
# Make the base tables bigger, so that it looks tempting to join the
# smaller lateral derived table first in the queries below. The
# optimizer needs to resist the temptation, because the lateral
# derived table cannot be joined before the table it depends on.
INSERT INTO t (a)
WITH RECURSIVE 150tup(n) AS
(SELECT 1 UNION ALL SELECT n + 1 FROM 150tup WHERE n < 150)
SELECT n FROM 150tup;
ANALYZE TABLE t;
SELECT /*+ SET_VAR(optimizer_max_subgraph_pairs = 1) */ COUNT(*)
FROM t AS t1 LEFT JOIN t AS t2 ON TRUE
WHERE t1.a IN (SELECT * FROM (SELECT DISTINCT t2.a) AS t3);
SELECT /*+ SET_VAR(optimizer_max_subgraph_pairs = 1) */ COUNT(*)
FROM t AS t1 LEFT JOIN t AS t2 ON TRUE,
LATERAL (SELECT DISTINCT t2.a FROM t) AS t3
WHERE t1.a = t3.a;
SELECT /*+ SET_VAR(optimizer_max_subgraph_pairs = 1) */ COUNT(*)
FROM t AS t1 LEFT JOIN t AS t2 ON 1,
JSON_TABLE(t2.b, '$[*]' COLUMNS(i INT PATH '$[0]')) AS t3
WHERE t3.i < 10 AND t1.a = t3.i;
DROP TABLE t;
--echo #
--echo # Bug#36098954: Assertion GraphSimplifier::EdgesAreNeighboring
--echo # failed with hypergraph_optimizer
--echo #
CREATE TABLE t(x INT);
SELECT /*+ SET_VAR(optimizer_max_subgraph_pairs = 1) */ 1
FROM t WHERE x IN (
SELECT NULL FROM t AS t1, t AS t2 STRAIGHT_JOIN t AS t3 ON t2.x = t3.x
) OR x = 1;
DROP TABLE t;