| # 2023 Feb 17 |
| # |
| # The author disclaims copyright to this source code. In place of |
| # a legal notice, here is a blessing: |
| # |
| # May you do good and not evil. |
| # May you find forgiveness for yourself and forgive others. |
| # May you share freely, never taking more than you give. |
| # |
| #************************************************************************* |
| # |
| |
| source [file join [file dirname [info script]] fts5_common.tcl] |
| ifcapable !fts5 { finish_test ; return } |
| set ::testprefix fts5secure |
| |
| proc dump {tname} { |
| execsql_pp "SELECT * FROM ${tname}_idx" |
| execsql_pp "SELECT id, quote(block), fts5_decode(id,block) FROM ${tname}_data" |
| } |
| |
| |
| do_execsql_test 0.0 { |
| CREATE VIRTUAL TABLE t1 USING fts5(ab); |
| CREATE VIRTUAL TABLE v1 USING fts5vocab('t1', 'instance'); |
| INSERT INTO t1(rowid, ab) VALUES |
| (0,'abc'), (1,'abc'), (2,'abc'), (3,'abc'), (4,'def'); |
| } |
| |
| do_execsql_test 0.1 { |
| INSERT INTO t1(t1, rank) VALUES('secure-delete', 1); |
| } |
| |
| do_execsql_test 0.2 { |
| DELETE FROM t1 WHERE rowid=2; |
| } |
| |
| do_execsql_test 0.3 { |
| SELECT count(*) FROM t1_data |
| } 3 |
| |
| do_execsql_test 0.4 { |
| INSERT INTO t1(t1) VALUES('integrity-check'); |
| } |
| |
| do_execsql_test 0.5 { |
| DELETE FROM t1 WHERE rowid=3; |
| } |
| |
| do_execsql_test 0.6 { |
| INSERT INTO t1(t1) VALUES('integrity-check'); |
| } |
| |
| do_execsql_test 0.7 { |
| DELETE FROM t1 WHERE rowid=0; |
| } |
| |
| do_execsql_test 0.8 { |
| INSERT INTO t1(t1) VALUES('integrity-check'); |
| } |
| |
| #---------------------------------- |
| |
| do_execsql_test 1.0 { |
| CREATE VIRTUAL TABLE t2 USING fts5(ab); |
| INSERT INTO t2(rowid, ab) VALUES (5, 'key'), (6, 'value'); |
| INSERT INTO t2(t2, rank) VALUES('secure-delete', 1); |
| } |
| |
| #execsql_pp { SELECT id, quote(block) FROM t1_data } |
| #execsql_pp { SELECT segid, quote(term), pgno FROM t1_idx } |
| |
| do_execsql_test 1.1 { |
| DELETE FROM t2 WHERE rowid = 5; |
| } |
| |
| do_execsql_test 1.2 { |
| INSERT INTO t2(t2) VALUES('integrity-check'); |
| } |
| |
| do_execsql_test 1.3 { |
| DELETE FROM t2 WHERE rowid = 6; |
| } |
| |
| do_execsql_test 1.4 { |
| INSERT INTO t2(t2) VALUES('integrity-check'); |
| } |
| |
| do_execsql_test 1.5 { |
| SELECT * FROM t2('value'); |
| SELECT * FROM t2('v*'); |
| } |
| |
| do_execsql_test 1.6 { |
| SELECT * FROM t2('value') ORDER BY rowid DESC; |
| SELECT * FROM t2('v*') ORDER BY rowid DESC; |
| } |
| execsql_pp { |
| SELECT id, quote(block) FROM t2_data; |
| } |
| |
| #---------------------------------- |
| |
| do_execsql_test 2.0 { |
| CREATE VIRTUAL TABLE ft USING fts5(ab); |
| CREATE VIRTUAL TABLE vocab USING fts5vocab('ft', 'instance'); |
| INSERT INTO ft(rowid, ab) VALUES |
| (1, 'one'), |
| (2, 'two'), |
| (3, 'three'), |
| (4, 'four'), |
| (5, 'one one'), |
| (6, 'one two'), |
| (7, 'one three'), |
| (8, 'one four'), |
| (9, 'two one'), |
| (10, 'two two'), |
| (11, 'two three'), |
| (12, 'two four'), |
| (13, 'three one'), |
| (14, 'three two'), |
| (15, 'three three'), |
| (16, 'three four'); |
| } |
| |
| do_execsql_test 2.1 { |
| SELECT count(*) FROM ft_data; |
| } {3} |
| |
| do_execsql_test 2.2 { |
| INSERT INTO ft(ft, rank) VALUES('secure-delete', 1); |
| } |
| |
| do_execsql_test 2.3 { |
| DELETE FROM ft WHERE rowid=9; |
| } |
| |
| do_execsql_test 2.4 { |
| INSERT INTO ft(ft) VALUES('integrity-check'); |
| } |
| |
| do_execsql_test 2.5 { |
| DELETE FROM ft WHERE ab LIKE '%two%' |
| } |
| |
| do_execsql_test 2.6 { |
| INSERT INTO ft(ft) VALUES('integrity-check'); |
| } |
| |
| do_execsql_test 2.7 { |
| SELECT count(*) FROM ft_data; |
| } {3} |
| |
| #---------------------------------- |
| reset_db |
| |
| set ::vocab { |
| one two three four five six seven eight nine ten |
| eleven twelve thirteen fourteen fifteen sixteen |
| seventeen eighteen nineteen twenty |
| } |
| proc rnddoc {} { |
| set nVocab [llength $::vocab] |
| set ret [list] |
| for {set ii 0} {$ii < 8} {incr ii} { |
| lappend ret [lindex $::vocab [expr int(abs(rand()) * $nVocab)]] |
| } |
| set ret |
| } |
| |
| proc contains {list val} { |
| expr {[lsearch $list $val]>=0} |
| } |
| |
| foreach {tn pgsz} { |
| 2 64 |
| 1 1000 |
| } { |
| reset_db |
| db function rnddoc rnddoc |
| db function contains contains |
| |
| expr srand(1) |
| |
| do_execsql_test 3.$tn.0 { |
| CREATE VIRTUAL TABLE t1 USING fts5(x); |
| INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz); |
| WITH s(i) AS ( |
| VALUES(1) UNION SELECT i+1 FROM s WHERE i<20 |
| ) |
| INSERT INTO t1 SELECT rnddoc() FROM s; |
| } |
| |
| do_execsql_test 3.$tn.1 { |
| INSERT INTO t1(t1, rank) VALUES('secure-delete', 1); |
| } |
| |
| foreach {rowid} { |
| 6 16 3 4 9 14 13 7 20 15 19 10 11 2 5 18 17 1 12 8 |
| } { |
| |
| do_execsql_test 3.$tn.2.$rowid { |
| DELETE FROM t1 WHERE rowid=$rowid; |
| } |
| do_execsql_test 3.$tn.2.$rowid.ic { |
| INSERT INTO t1(t1) VALUES('integrity-check'); |
| } |
| |
| foreach v $::vocab { |
| do_execsql_test 3.$tn.2.$rowid.q.$v { |
| SELECT rowid FROM t1($v) |
| } [db eval {SELECT rowid FROM t1 WHERE contains(x, $v)}] |
| |
| do_execsql_test 3.$tn.2.$rowid.q.$v.DESC { |
| SELECT rowid FROM t1($v) ORDER BY 1 DESC |
| } [db eval {SELECT rowid FROM t1 WHERE contains(x, $v) ORDER BY 1 DESC}] |
| } |
| } |
| } |
| |
| do_execsql_test 3.3 { |
| INSERT INTO t1(x) VALUES('optimize'); |
| INSERT INTO t1(t1) VALUES('optimize'); |
| SELECT count(*) FROM t1_data; |
| } {3} |
| |
| #---------------------------------- |
| reset_db |
| do_execsql_test 4.0 { |
| CREATE VIRTUAL TABLE t1 USING fts5(x); |
| INSERT INTO t1(t1, rank) VALUES('pgsz', 32); |
| INSERT INTO t1(t1, rank) VALUES('secure-delete', 1); |
| } |
| |
| set L1 [string repeat abcdefghij 10] |
| set L2 [string repeat 1234567890 10] |
| |
| do_execsql_test 4.1 { |
| INSERT INTO t1 VALUES('aa' || $L1 || ' ' || $L2); |
| } |
| do_execsql_test 4.2 { |
| DELETE FROM t1 WHERE rowid=1 |
| } |
| do_execsql_test 4.3 { |
| INSERT INTO t1(t1) VALUES('integrity-check'); |
| } |
| |
| #---------------------------------- |
| reset_db |
| do_execsql_test 5.0 { |
| CREATE VIRTUAL TABLE t1 USING fts5(x); |
| INSERT INTO t1(t1, rank) VALUES('pgsz', 32); |
| INSERT INTO t1(t1, rank) VALUES('secure-delete', 1); |
| } |
| |
| set doc "aa [string repeat {abc } 60]" |
| |
| do_execsql_test 5.1 { |
| BEGIN; |
| INSERT INTO t1 VALUES($doc); |
| INSERT INTO t1 VALUES('aa abc'); |
| COMMIT; |
| } |
| |
| do_execsql_test 5.2 { |
| DELETE FROM t1 WHERE rowid = 1; |
| } |
| |
| do_execsql_test 5.3 { |
| INSERT INTO t1(t1) VALUES('integrity-check'); |
| } |
| |
| do_execsql_test 5.4 { SELECT rowid FROM t1('abc'); } 2 |
| do_execsql_test 5.5 { SELECT rowid FROM t1('aa'); } 2 |
| |
| #------------------------------------------------------------------------- |
| # Tests for the bug fixed by https://sqlite.org/src/info/4b60a1c3 |
| # |
| reset_db |
| do_execsql_test 6.0 { |
| CREATE VIRTUAL TABLE fts USING fts5(content); |
| INSERT INTO fts(fts, rank) VALUES ('secure-delete', 1); |
| INSERT INTO fts(rowid, content) VALUES |
| (3407, 'profile profile profile profile profile profile profile profile pull pulling pulling really'); |
| DELETE FROM fts WHERE rowid IS 3407; |
| INSERT INTO fts(fts) VALUES ('integrity-check'); |
| } |
| |
| foreach {tn detail} { |
| 1 full |
| 2 column |
| 3 none |
| } { |
| do_execsql_test 6.1.$detail " |
| DROP TABLE IF EXISTS t1; |
| CREATE VIRTUAL TABLE t1 USING fts5(x, detail=$detail); |
| " |
| |
| do_execsql_test 6.2.$detail { |
| INSERT INTO t1(t1, rank) VALUES('secure-delete', 1); |
| } |
| |
| for {set ii 1} {$ii < 100} {incr ii} { |
| do_execsql_test 6.3.$detail.$ii.1 { |
| BEGIN; |
| INSERT INTO t1(rowid, x) VALUES(10, 'word1'); |
| WITH s(i) AS ( |
| SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<CAST($ii AS integer) |
| ) |
| INSERT INTO t1(x) SELECT 'word3' FROM s; |
| COMMIT; |
| INSERT INTO t1(t1) VALUES('optimize'); |
| } |
| |
| do_execsql_test 6.3.$detail.$ii.2 { |
| DELETE FROM t1 WHERE rowid=10; |
| INSERT INTO t1(t1) VALUES ('integrity-check'); |
| } |
| |
| do_execsql_test 6.3.$detail.$ii.3 { |
| DELETE FROM t1; |
| } |
| |
| do_execsql_test 6.3.$detail.$ii.4 { |
| BEGIN; |
| INSERT INTO t1(rowid, x) VALUES(10, 'tokenA'); |
| WITH s(i) AS ( |
| SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<CAST($ii AS integer) |
| ) |
| INSERT INTO t1(x) SELECT group_concat('tokenB ') FROM s; |
| COMMIT; |
| INSERT INTO t1(t1) VALUES('optimize'); |
| } |
| |
| do_execsql_test 6.3.$detail.$ii.5 { |
| DELETE FROM t1 WHERE rowid=10; |
| INSERT INTO t1(t1) VALUES ('integrity-check'); |
| } |
| |
| do_execsql_test 6.3.$detail.$ii.6 { |
| DELETE FROM t1; |
| } |
| } |
| } |
| |
| |
| finish_test |
| |