| Index: third_party/sqlite/sqlite-src-3100200/test/analyze9.test
|
| diff --git a/third_party/sqlite/src/test/analyze9.test b/third_party/sqlite/sqlite-src-3100200/test/analyze9.test
|
| similarity index 90%
|
| copy from third_party/sqlite/src/test/analyze9.test
|
| copy to third_party/sqlite/sqlite-src-3100200/test/analyze9.test
|
| index 8572cbea0044a58f3bcb131c58c49f61f4b38562..1ebd69c8d18f22c61944181eafcfc96cfb723b05 100644
|
| --- a/third_party/sqlite/src/test/analyze9.test
|
| +++ b/third_party/sqlite/sqlite-src-3100200/test/analyze9.test
|
| @@ -1134,4 +1134,116 @@ ifcapable stat4&&cte {
|
| }
|
| }
|
|
|
| +#-------------------------------------------------------------------------
|
| +# Check that a problem in they way stat4 data is used has been
|
| +# resolved (see below).
|
| +#
|
| +reset_db
|
| +do_test 26.1.1 {
|
| + db transaction {
|
| + execsql {
|
| + CREATE TABLE t1(x, y, z);
|
| + CREATE INDEX t1xy ON t1(x, y);
|
| + CREATE INDEX t1z ON t1(z);
|
| + }
|
| + for {set i 0} {$i < 10000} {incr i} {
|
| + execsql { INSERT INTO t1(x, y) VALUES($i, $i) }
|
| + }
|
| + for {set i 0} {$i < 10} {incr i} {
|
| + execsql {
|
| + WITH cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt WHERE x<100)
|
| + INSERT INTO t1(x, y) SELECT 10000+$i, x FROM cnt;
|
| + INSERT INTO t1(x, y) SELECT 10000+$i, 100;
|
| + }
|
| + }
|
| + execsql {
|
| + UPDATE t1 SET z = rowid / 20;
|
| + ANALYZE;
|
| + }
|
| + }
|
| +} {}
|
| +
|
| +do_execsql_test 26.1.2 {
|
| + SELECT count(*) FROM t1 WHERE x = 10000 AND y < 50;
|
| +} {49}
|
| +do_execsql_test 26.1.3 {
|
| + SELECT count(*) FROM t1 WHERE z = 444;
|
| +} {20}
|
| +
|
| +# The analyzer knows that any (z=?) expression matches 20 rows. So it
|
| +# will use index "t1z" if the estimate of hits for (x=10000 AND y<50)
|
| +# is greater than 20 rows.
|
| +#
|
| +# And it should be. The analyzer has a stat4 sample as follows:
|
| +#
|
| +# sample=(x=10000, y=100) nLt=(10000 10099)
|
| +#
|
| +# There should be no other samples that start with (x=10000). So it knows
|
| +# that (x=10000 AND y<50) must match somewhere between 0 and 99 rows, but
|
| +# know more than that. Guessing less than 20 is therefore unreasonable.
|
| +#
|
| +# At one point though, due to a problem in whereKeyStats(), the planner was
|
| +# estimating that (x=10000 AND y<50) would match only 2 rows.
|
| +#
|
| +do_eqp_test 26.1.4 {
|
| + SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
|
| +} {
|
| + 0 0 0 {SEARCH TABLE t1 USING INDEX t1z (z=?)}
|
| +}
|
| +
|
| +
|
| +# This test - 26.2.* - tests that another manifestation of the same problem
|
| +# is no longer present in the library. Assuming:
|
| +#
|
| +# CREATE INDEX t1xy ON t1(x, y)
|
| +#
|
| +# and that have samples for index t1xy as follows:
|
| +#
|
| +#
|
| +# sample=('A', 70) nEq=(100, 2) nLt=(900, 970)
|
| +# sample=('B', 70) nEq=(100, 2) nLt=(1000, 1070)
|
| +#
|
| +# the planner should estimate that (x = 'B' AND y > 25) matches 76 rows
|
| +# (70 * 2/3 + 30). Before, due to the problem, the planner was estimating
|
| +# that this matched 100 rows.
|
| +#
|
| +reset_db
|
| +do_execsql_test 26.2.1 {
|
| + BEGIN;
|
| + CREATE TABLE t1(x, y, z);
|
| + CREATE INDEX i1 ON t1(x, y);
|
| + CREATE INDEX i2 ON t1(z);
|
| +
|
| + WITH
|
| + cnt(y) AS (SELECT 0 UNION ALL SELECT y+1 FROM cnt WHERE y<99),
|
| + letters(x) AS (
|
| + SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D'
|
| + )
|
| + INSERT INTO t1(x, y) SELECT x, y FROM letters, cnt;
|
| +
|
| + WITH
|
| + letters(x) AS (
|
| + SELECT 'A' UNION SELECT 'B' UNION SELECT 'C' UNION SELECT 'D'
|
| + )
|
| + INSERT INTO t1(x, y) SELECT x, 70 FROM letters;
|
| +
|
| + WITH
|
| + cnt(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM cnt WHERE i<9999)
|
| + INSERT INTO t1(x, y) SELECT i, i FROM cnt;
|
| +
|
| + UPDATE t1 SET z = (rowid / 95);
|
| + ANALYZE;
|
| + COMMIT;
|
| +}
|
| +
|
| +do_eqp_test 26.2.2 {
|
| + SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
|
| +} {
|
| + 0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
|
| +}
|
| +
|
| +
|
| finish_test
|
| +
|
| +
|
| +
|
|
|