CoolFace
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
pushdown.test360 linesDownload Raw Back to test
1# 2017-04-292#3# The author disclaims copyright to this source code.  In place of4# a legal notice, here is a blessing:5#6#    May you do good and not evil.7#    May you find forgiveness for yourself and forgive others.8#    May you share freely, never taking more than you give.9#10#***********************************************************************11#12# Test cases for the push-down optimizations.13#14#15# There are two different meanings for "push-down optimization".16#17#   (1)  "MySQL push-down" means that WHERE clause terms that can be18#        evaluated using only the index and without reference to the19#        table are run first, so that if they are false, unnecessary table20#        seeks are avoided.  See https://sqlite.org/src/info/d7bb79ed3a40419d21#        from 2017-04-29.22#23#   (2)  "WHERE-clause pushdown" means to push WHERE clause terms in24#        outer queries down into subqueries.  See25#        https://sqlite.org/src/info/6df18e949d367629 from 2015-06-02.26#27# This module started out as tests for MySQL push-down only.  But because28# of naming ambiguity, it has picked up test cases for WHERE-clause push-down29# over the years.30#31 32set testdir [file dirname $argv0]33source $testdir/tester.tcl34set testprefix pushdown35 36do_execsql_test 1.0 {37  CREATE TABLE t1(a, b, c);38  INSERT INTO t1 VALUES(1, 'b1', 'c1');39  INSERT INTO t1 VALUES(2, 'b2', 'c2');40  INSERT INTO t1 VALUES(3, 'b3', 'c3');41  INSERT INTO t1 VALUES(4, 'b4', 'c4');42  CREATE INDEX i1 ON t1(a, c);43}44 45proc f {val} {46  lappend ::L $val47  return 048}49db func f f 50 51do_test 1.1 {52  set L [list]53  execsql { SELECT * FROM t1 WHERE a=2 AND f(b) AND f(c) }54  set L55} {c2}56 57do_test 1.2 {58  set L [list]59  execsql { SELECT * FROM t1 WHERE a=3 AND f(c) AND f(b) }60  set L61} {c3}62 63do_execsql_test 1.3 {64  DROP INDEX i1;65  CREATE INDEX i1 ON t1(a, b);66}67do_test 1.4 {68  set L [list]69  execsql { SELECT * FROM t1 WHERE a=2 AND f(b) AND f(c) }70  set L71} {b2}72 73do_test 1.5 {74  set L [list]75  execsql { SELECT * FROM t1 WHERE a=3 AND f(c) AND f(b) }76  set L77} {b3}78 79#-----------------------------------------------80 81do_execsql_test 2.0 {82  CREATE TABLE u1(a, b, c);83  CREATE TABLE u2(x, y, z);84 85  INSERT INTO u1 VALUES('a1', 'b1', 'c1');86  INSERT INTO u2 VALUES('a1', 'b1', 'c1');87}88 89do_test 2.1 {90  set L [list]91  execsql {92    SELECT * FROM u1 WHERE f('one')=123 AND 123=(93      SELECT x FROM u2 WHERE x=a AND f('two')94    )95  }96  set L97} {one}98 99do_test 2.2 {100  set L [list]101  execsql {102    SELECT * FROM u1 WHERE 123=(103      SELECT x FROM u2 WHERE x=a AND f('two')104    ) AND f('three')=123105  }106  set L107} {three}108 109# 2022-11-25 dbsqlfuzz crash-3a548de406a50e896c1bf7142692d35d339d697f110# Disable the WHERE-clause push-down optimization for compound subqueries111# if any arm of the compound has an incompatible affinity.112#113reset_db114do_execsql_test 3.1 {115  CREATE TABLE t0(c0 INT);116  INSERT INTO t0 VALUES(0);117  CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT);118  INSERT INTO t1_a VALUES(1,'one');119  CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT);120  INSERT INTO t1_b VALUES(2,'two');121  CREATE VIEW v0 AS SELECT CAST(t0.c0 AS INTEGER) AS c0 FROM t0;122  CREATE VIEW v1(a,b) AS SELECT a, b FROM t1_a UNION ALL SELECT c, 0 FROM t1_b;123  SELECT v1.a, quote(v1.b), t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0,v1;124} {125  1 'one' 0126  2 0     0127}128do_execsql_test 3.2 {129  SELECT a, quote(b), cd FROM (130    SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1131  ) WHERE a=2 AND b='0' AND cd=0;132} {}133do_execsql_test 3.3 {134  SELECT a, quote(b), cd FROM (135    SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1136  ) WHERE a=1 AND b='one' AND cd=0;137} {1 'one' 0}138do_execsql_test 3.4 {139  SELECT a, quote(b), cd FROM (140    SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1141  ) WHERE a=2 AND b=0 AND cd=0;142} {143  2 0     0144}145 146# 2023-02-22 https://sqlite.org/forum/forumpost/bcc4375032147# Performance regression caused by check-in [1ad41840c5e0fa70] from 2022-11-25.148# That check-in added a new restriction on push-down.  The new restriction is149# no longer necessary after check-in [27655c9353620aa5] from 2022-12-14.150#151do_execsql_test 3.5 {152  DROP TABLE IF EXISTS t1;153  CREATE TABLE t1(a INT, b INT, c TEXT, PRIMARY KEY(a,b)) WITHOUT ROWID;154  INSERT INTO t1(a,b,c) VALUES155    (1,100,'abc'),156    (2,200,'def'),157    (3,300,'abc');158  DROP TABLE IF EXISTS t2;159  CREATE TABLE t2(a INT, b INT, c TEXT, PRIMARY KEY(a,b)) WITHOUT ROWID;160  INSERT INTO t2(a,b,c) VALUES161    (1,110,'efg'),162    (2,200,'hij'),163    (3,330,'klm');164  CREATE VIEW v3 AS165    SELECT a, b, c FROM t1166    UNION ALL167    SELECT a, b, 'xyz' FROM t2;168  SELECT * FROM v3 WHERE a=2 AND b=200;169} {2 200 def 2 200 xyz}170do_eqp_test 3.6 {171  SELECT * FROM v3 WHERE a=2 AND b=200;172} {173  QUERY PLAN174  |--CO-ROUTINE v3175  |  `--COMPOUND QUERY176  |     |--LEFT-MOST SUBQUERY177  |     |  `--SEARCH t1 USING PRIMARY KEY (a=? AND b=?)178  |     `--UNION ALL179  |        `--SEARCH t2 USING PRIMARY KEY (a=? AND b=?)180  `--SCAN v3181}182#                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^183# We want both arms of the compound subquery to use the184# primary key.185 186# The following is a test of the count-of-view optimization.  This does187# not have anything to do with push-down.  It is here because this is a188# convenient place to put the test.189#190do_execsql_test 3.7 {191  SELECT count(*) FROM v3;192} 6193do_eqp_test 3.8 {194  SELECT count(*) FROM v3;195} {196  QUERY PLAN197  |--SCAN CONSTANT ROW198  |--SCALAR SUBQUERY xxxxxx199  |  `--SCAN t1200  `--SCALAR SUBQUERY xxxxxx201     `--SCAN t2202}203# ^^^^^^^^^^^^^^^^^^^^204# The query should be converted into:205#   SELECT (SELECT count(*) FROM t1)+(SELECT count(*) FROM t2)206 207# 2023-05-09 https://sqlite.org/forum/forumpost/a7d4be7fb6208# Restriction (9) on the WHERE-clause push-down optimization.209# 210reset_db211db null -212do_execsql_test 4.1 {213  CREATE TABLE t1(a INT);214  CREATE TABLE t2(b INT);215  CREATE TABLE t3(c INT);216  INSERT INTO t3(c) VALUES(3);217  CREATE TABLE t4(d INT);218  CREATE TABLE t5(e INT);219  INSERT INTO t5(e) VALUES(5);220  CREATE VIEW v6(f,g) AS SELECT d, e FROM t4 RIGHT JOIN t5 ON true;221  SELECT * FROM  t1 JOIN t2 ON false RIGHT JOIN t3 ON true CROSS JOIN v6;222} {- - 3 - 5}223do_execsql_test 4.2 {224  SELECT * FROM v6 JOIN t5 ON false RIGHT JOIN t3 ON true;225} {- - - 3}226do_execsql_test 4.3 {227  SELECT * FROM t1 JOIN t2 ON false JOIN v6 ON true RIGHT JOIN t3 ON true;228} {- - - - 3}229 230# 2023-05-15 https://sqlite.org/forum/forumpost/f3f546025a231# This is restriction (6) on sqlite3ExprIsSingleTableConstraint().232# That restriction (now) used to implement restriction (9) on push-down.233# It is used for other things too, so it is not purely a push-down234# restriction.  But it seems convenient to put it here.235#236reset_db237db null -238do_execsql_test 5.0 {239  CREATE TABLE t1(a INT);  INSERT INTO t1 VALUES(1);240  CREATE TABLE t2(b INT);  INSERT INTO t2 VALUES(2);241  CREATE TABLE t3(c INT);  INSERT INTO t3 VALUES(3);242  CREATE TABLE t4(d INT);  INSERT INTO t4 VALUES(4);243  CREATE TABLE t5(e INT);  INSERT INTO t5 VALUES(5);244  SELECT *245    FROM t1 JOIN t2 ON null RIGHT JOIN t3 ON true246          LEFT JOIN (t4 JOIN t5 ON d+1=e) ON d=4247   WHERE e>0;248} {- - 3 4 5}249 250 251# 2024-04-05252# Allow push-down of operators of the form "expr IN table".253#254reset_db255do_execsql_test 6.0 {256  CREATE TABLE t01(w,x,y,z);257  CREATE TABLE t02(w,x,y,z);258  CREATE VIEW t0(w,x,y,z) AS259    SELECT w,x,y,z FROM t01 UNION ALL SELECT w,x,y,z FROM t02;260  CREATE INDEX t01x ON t01(w,x,y);261  CREATE INDEX t02x ON t02(w,x,y);262  CREATE VIEW v1(k) AS VALUES(77),(88),(99);263  CREATE TABLE k1(k);264  INSERT INTO k1 SELECT * FROM v1;265}266do_eqp_test 6.1 {267  WITH k(n) AS (VALUES(77),(88),(99))268  SELECT max(z) FROM t0 WHERE w=123 AND x IN k AND y BETWEEN 44 AND 55;269} {270  QUERY PLAN271  |--CO-ROUTINE t0272  |  `--COMPOUND QUERY273  |     |--LEFT-MOST SUBQUERY274  |     |  |--SEARCH t01 USING INDEX t01x (w=? AND x=? AND y>? AND y<?)275  |     |  `--LIST SUBQUERY xxxxxx276  |     |     |--MATERIALIZE k277  |     |     |  `--SCAN 3 CONSTANT ROWS278  |     |     |--SCAN k279  |     |     `--CREATE BLOOM FILTER280  |     `--UNION ALL281  |        |--SEARCH t02 USING INDEX t02x (w=? AND x=? AND y>? AND y<?)282  |        `--REUSE LIST SUBQUERY xxxxxx283  |--SEARCH t0284  `--REUSE LIST SUBQUERY xxxxxx285}286# ^^^^--- The key feature above is that the SEARCH for each subquery287# uses all three fields of the index w, x, and y.  Prior to the push-down288# of "expr IN table", only the w term of the index would be used.  Similar289# for the following tests:290#291do_eqp_test 6.2 {292  SELECT max(z) FROM t0 WHERE w=123 AND x IN v1 AND y BETWEEN 44 AND 55;293} {294  QUERY PLAN295  |--CO-ROUTINE t0296  |  `--COMPOUND QUERY297  |     |--LEFT-MOST SUBQUERY298  |     |  |--SEARCH t01 USING INDEX t01x (w=? AND x=? AND y>? AND y<?)299  |     |  `--LIST SUBQUERY xxxxxx300  |     |     |--CO-ROUTINE v1301  |     |     |  `--SCAN 3 CONSTANT ROWS302  |     |     |--SCAN v1303  |     |     `--CREATE BLOOM FILTER304  |     `--UNION ALL305  |        |--SEARCH t02 USING INDEX t02x (w=? AND x=? AND y>? AND y<?)306  |        `--REUSE LIST SUBQUERY xxxxxx307  |--SEARCH t0308  `--REUSE LIST SUBQUERY xxxxxx309}310do_eqp_test 6.3 {311  SELECT max(z) FROM t0 WHERE w=123 AND x IN k1 AND y BETWEEN 44 AND 55;312} {313  QUERY PLAN314  |--CO-ROUTINE t0315  |  `--COMPOUND QUERY316  |     |--LEFT-MOST SUBQUERY317  |     |  |--SEARCH t01 USING INDEX t01x (w=? AND x=? AND y>? AND y<?)318  |     |  `--LIST SUBQUERY xxxxxx319  |     |     |--SCAN k1320  |     |     `--CREATE BLOOM FILTER321  |     `--UNION ALL322  |        |--SEARCH t02 USING INDEX t02x (w=? AND x=? AND y>? AND y<?)323  |        `--REUSE LIST SUBQUERY xxxxxx324  |--SEARCH t0325  `--REUSE LIST SUBQUERY xxxxxx326}327 328#-------------------------------------------------------------------------329reset_db330do_execsql_test 7.0 {331  CREATE  TABLE  t0_1(a INT , b INT, c INT);332  CREATE  TABLE  t0_2(a INT , b INT, c INT);333 334  INSERT INTO t0_1 (a, b, c) VALUES (1, 0, 1);335  INSERT INTO t0_2 (a, b, c) VALUES (1, 0, 1);336 337  CREATE  TABLE  empty1(x);338  CREATE  TABLE  empty2(y);339}340 341do_execsql_test 7.1 {342  SELECT t0_2.c343    FROM (SELECT '0000' AS c0 FROM empty2 RIGHT JOIN t0_1 ON 1) AS v0 344    LEFT JOIN empty1 ON v0.c0, t0_2 345    RIGHT JOIN (346           SELECT 5678 AS col0 FROM (SELECT 0)347    ) AS sub1 ON 1;348} {1}349 350do_execsql_test 7.2 {351  SELECT t0_2.c352    FROM (SELECT '0000' AS c0 FROM empty2 RIGHT JOIN t0_1 ON 1) AS v0 353    LEFT JOIN empty1 ON v0.c0, t0_2 354    RIGHT JOIN (355           SELECT 5678 AS col0 FROM (SELECT 0)356    ) AS sub1 ON 1 WHERE +t0_2.c;357} {1}358 359finish_test360