xref: /sqlite-3.40.0/test/analyzeF.test (revision 8210233c)
118bf8076Sdan# 2015-03-12
218bf8076Sdan#
318bf8076Sdan# The author disclaims copyright to this source code.  In place of
418bf8076Sdan# a legal notice, here is a blessing:
518bf8076Sdan#
618bf8076Sdan#    May you do good and not evil.
718bf8076Sdan#    May you find forgiveness for yourself and forgive others.
818bf8076Sdan#    May you share freely, never taking more than you give.
918bf8076Sdan#
1018bf8076Sdan#***********************************************************************
1118bf8076Sdan# Test that deterministic scalar functions passed constant arguments
1218bf8076Sdan# are used with stat4 data.
1318bf8076Sdan#
1418bf8076Sdan
1518bf8076Sdanset testdir [file dirname $argv0]
1618bf8076Sdansource $testdir/tester.tcl
1718bf8076Sdanset ::testprefix analyzeF
1818bf8076Sdan
1918bf8076Sdanifcapable {!stat4} {
2018bf8076Sdan  finish_test
2118bf8076Sdan  return
2218bf8076Sdan}
2318bf8076Sdan
2418bf8076Sdanproc isqrt {i} { expr { int(sqrt($i)) } }
2518bf8076Sdandb func isqrt isqrt
2618bf8076Sdan
2718bf8076Sdando_execsql_test 1.0 {
2818bf8076Sdan  CREATE TABLE t1(x INTEGER, y INTEGER);
2918bf8076Sdan  WITH data(i) AS (
3018bf8076Sdan    SELECT 1 UNION ALL SELECT i+1 FROM data
3118bf8076Sdan  )
3218bf8076Sdan  INSERT INTO t1 SELECT isqrt(i), isqrt(i) FROM data LIMIT 400;
3318bf8076Sdan  CREATE INDEX t1x ON t1(x);
3418bf8076Sdan  CREATE INDEX t1y ON t1(y);
3518bf8076Sdan  ANALYZE;
3618bf8076Sdan}
3718bf8076Sdan
3818bf8076Sdanproc str {a} { return $a }
3918bf8076Sdandb func str str
4018bf8076Sdan
4118bf8076Sdan# Note: tests 7 to 12 might be unstable - as they assume SQLite will
4218bf8076Sdan# prefer the expression to the right of the AND clause. Which of
4318bf8076Sdan# course could change.
4418bf8076Sdan#
4518bf8076Sdan# Note 2: tests 9 and 10 depend on the tcl interface creating functions
4618bf8076Sdan# without the SQLITE_DETERMINISTIC flag set.
4718bf8076Sdan#
4818bf8076Sdanforeach {tn where idx} {
4918bf8076Sdan  1 "x = 4 AND y = 19"     {t1x (x=?)}
5018bf8076Sdan  2 "x = 19 AND y = 4"     {t1y (y=?)}
5118bf8076Sdan  3 "x = '4' AND y = '19'" {t1x (x=?)}
5218bf8076Sdan  4 "x = '19' AND y = '4'" {t1y (y=?)}
5318bf8076Sdan  5 "x = substr('5195', 2, 2) AND y = substr('145', 2, 1)" {t1y (y=?)}
5418bf8076Sdan  6 "x = substr('145', 2, 1) AND y = substr('5195', 2, 2)" {t1x (x=?)}
5518bf8076Sdan
5618bf8076Sdan  7  "x = substr('5195', 2, 2+0) AND y = substr('145', 2, 1+0)" {t1y (y=?)}
5718bf8076Sdan  8  "x = substr('145', 2, 1+0) AND y = substr('5195', 2, 2+0)" {t1y (y=?)}
5818bf8076Sdan
5918bf8076Sdan  9  "x = str('19') AND y = str('4')" {t1y (y=?)}
6018bf8076Sdan  10 "x = str('4') AND y = str('19')" {t1y (y=?)}
6118bf8076Sdan
6218bf8076Sdan  11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
6318bf8076Sdan  12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
6418bf8076Sdan} {
65*8210233cSdrh  set res "SEARCH t1 USING INDEX $idx"
6618bf8076Sdan  do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
6718bf8076Sdan}
6818bf8076Sdan
693df30592Sdan# Test that functions that do not exist - "func()" - do not cause an error.
703df30592Sdan#
7118bf8076Sdando_catchsql_test 2.1 {
7218bf8076Sdan  SELECT * FROM t1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
7318bf8076Sdan} {1 {no such function: func}}
7418bf8076Sdando_catchsql_test 2.2 {
7518bf8076Sdan  UPDATE t1 SET y=y+1 WHERE x = substr('145', 2, 1) AND y = func(1, 2, 3)
7618bf8076Sdan} {1 {no such function: func}}
7718bf8076Sdan
7818bf8076Sdan
793df30592Sdan# Check that functions that accept zero arguments do not cause problems.
803df30592Sdan#
813df30592Sdanproc ret {x} { return $x }
823df30592Sdan
833df30592Sdandb func det4 -deterministic [list ret 4]
843df30592Sdandb func nondet4 [list ret 4]
853df30592Sdandb func det19 -deterministic [list ret 19]
863df30592Sdandb func nondet19 [list ret 19]
873df30592Sdan
883df30592Sdanforeach {tn where idx} {
893df30592Sdan  1 "x = det4() AND y = det19()"     {t1x (x=?)}
903df30592Sdan  2 "x = det19() AND y = det4()"     {t1y (y=?)}
913df30592Sdan
923df30592Sdan  3 "x = nondet4() AND y = nondet19()"     {t1y (y=?)}
933df30592Sdan  4 "x = nondet19() AND y = nondet4()"     {t1y (y=?)}
943df30592Sdan} {
95*8210233cSdrh  set res "SEARCH t1 USING INDEX $idx"
963df30592Sdan  do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
973df30592Sdan}
983df30592Sdan
993df30592Sdan
1003df30592Sdanexecsql { DELETE FROM t1 }
1013df30592Sdan
1023df30592Sdanproc throw_error {err} { error $err }
1033df30592Sdandb func error -deterministic throw_error
1043df30592Sdando_catchsql_test 4.1 {
1053df30592Sdan  SELECT * FROM t1 WHERE x = error('error one') AND y = 4;
1063df30592Sdan} {1 {error one}}
1073df30592Sdan
1083df30592Sdando_catchsql_test 4.2 {
109fa385edfSdrh  SELECT * FROM t1 WHERE x = zeroblob(2200000000) AND y = 4;
1103df30592Sdan} {1 {string or blob too big}}
1113df30592Sdan
1123df30592Sdansqlite3_limit db SQLITE_LIMIT_LENGTH 1000000
1133df30592Sdanproc dstr {} { return [string repeat x 1100000] }
1143df30592Sdandb func dstr -deterministic dstr
1153df30592Sdando_catchsql_test 4.3 {
1163df30592Sdan  SELECT * FROM t1 WHERE x = dstr() AND y = 11;
1173df30592Sdan} {1 {string or blob too big}}
1183df30592Sdan
1193df30592Sdando_catchsql_test 4.4 {
1203df30592Sdan  SELECT * FROM t1 WHERE x = test_zeroblob(1100000) AND y = 4;
1213df30592Sdan} {1 {string or blob too big}}
1223df30592Sdan
123e0568d6fSdrh# 2016-12-08: Constraints of the form "x=? AND x IS NOT NULL" were being
124e0568d6fSdrh# mishandled.  The sqlite3Stat4ProbeSetValue() routine was assuming that
125e0568d6fSdrh# valueNew() was returning a Mem object that was preset to NULL, which is
126e0568d6fSdrh# not the case.  The consequence was the the "x IS NOT NULL" constraint
127e0568d6fSdrh# was used to drive the index (via the "x>NULL" pseudo-constraint) rather
128e0568d6fSdrh# than the "x=?" constraint.
129e0568d6fSdrh#
130e0568d6fSdrhdo_execsql_test 5.1 {
131e0568d6fSdrh  DROP TABLE IF EXISTS t1;
132e0568d6fSdrh  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c INT);
133e0568d6fSdrh  WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10000)
134e0568d6fSdrh    INSERT INTO t1(a, c) SELECT x, x FROM c;
135e0568d6fSdrh  UPDATE t1 SET b=printf('x%02x',a/500) WHERE a>4000;
136e0568d6fSdrh  UPDATE t1 SET b='xyz' where a>=9998;
137e0568d6fSdrh  CREATE INDEX t1b ON t1(b);
138e0568d6fSdrh  ANALYZE;
139e0568d6fSdrh  SELECT count(*), b FROM t1 GROUP BY 2 ORDER BY 2;
140e0568d6fSdrh} {4000 {} 499 x08 500 x09 500 x0a 500 x0b 500 x0c 500 x0d 500 x0e 500 x0f 500 x10 500 x11 500 x12 498 x13 3 xyz}
141e0568d6fSdrhdo_execsql_test 5.2 {
142e0568d6fSdrh  explain query plan
143e0568d6fSdrh  SELECT * FROM t1 WHERE b='xyz' AND b IS NOT NULL ORDER BY +a;
144e0568d6fSdrh  /*                  v---- Should be "=", not ">"  */
145e0568d6fSdrh} {/USING INDEX t1b .b=/}
146e0568d6fSdrhdo_execsql_test 5.3 {
147e0568d6fSdrh  SELECT * FROM t1 WHERE b='xyz' AND b IS NOT NULL ORDER BY +a;
148e0568d6fSdrh} {9998 xyz 9998 9999 xyz 9999 10000 xyz 10000}
1493df30592Sdan
15018bf8076Sdanfinish_test
151