1*87ddfeb0Sdan# 297f267e0Sdan# 2010 September 17 397f267e0Sdan# 497f267e0Sdan# May you do good and not evil. 597f267e0Sdan# May you find forgiveness for yourself and forgive others. 697f267e0Sdan# May you share freely, never taking more than you give. 797f267e0Sdan# 897f267e0Sdan#*********************************************************************** 9*87ddfeb0Sdan# This file implements regression tests for SQLite library. The 10*87ddfeb0Sdan# focus of this file is the interactions between the FTS3/4 module 11*87ddfeb0Sdan# and shared-cache mode. 1297f267e0Sdan# 1397f267e0Sdan 1497f267e0Sdanset testdir [file dirname $argv0] 1597f267e0Sdansource $testdir/tester.tcl 1697f267e0Sdan 1797f267e0Sdanifcapable !fts3||!shared_cache { 1897f267e0Sdan finish_test 1997f267e0Sdan return 2097f267e0Sdan} 21*87ddfeb0Sdanset ::testprefix fts3shared 2297f267e0Sdan 2397f267e0Sdandb close 2497f267e0Sdanset ::enable_shared_cache [sqlite3_enable_shared_cache 1] 2597f267e0Sdan 2697f267e0Sdan# Open two connections to the database in shared-cache mode. 2797f267e0Sdan# 2897f267e0Sdansqlite3 db test.db 2997f267e0Sdansqlite3 db2 test.db 3097f267e0Sdan 3197f267e0Sdan# Create a virtual FTS3 table. Populate it with some initial data. 3297f267e0Sdan# 3397f267e0Sdando_execsql_test fts3shared-1.1 { 3497f267e0Sdan CREATE VIRTUAL TABLE t1 USING fts3(x); 3597f267e0Sdan BEGIN; 3697f267e0Sdan INSERT INTO t1 VALUES('We listened and looked sideways up!'); 3797f267e0Sdan INSERT INTO t1 VALUES('Fear at my heart, as at a cup,'); 3897f267e0Sdan INSERT INTO t1 VALUES('My life-blood seemed to sip!'); 3997f267e0Sdan INSERT INTO t1 VALUES('The stars were dim, and thick the night'); 4097f267e0Sdan COMMIT; 4197f267e0Sdan} {} 4297f267e0Sdan 4397f267e0Sdan# Open a write transaction and insert rows into the FTS3 table. This takes 4497f267e0Sdan# a write-lock on the underlying t1_content table. 4597f267e0Sdan# 4697f267e0Sdando_execsql_test fts3shared-1.2 { 4797f267e0Sdan BEGIN; 4897f267e0Sdan INSERT INTO t1 VALUES('The steersman''s face by his lamp gleamed white;'); 4997f267e0Sdan} {} 5097f267e0Sdan 5197f267e0Sdan# Now try a SELECT on the full-text table. This particular SELECT does not 5297f267e0Sdan# read data from the %_content table. But it still attempts to obtain a lock 5397f267e0Sdan# on that table and so the SELECT fails. 5497f267e0Sdan# 5597f267e0Sdando_test fts3shared-1.3 { 5697f267e0Sdan catchsql { 5797f267e0Sdan BEGIN; 5897f267e0Sdan SELECT rowid FROM t1 WHERE t1 MATCH 'stars' 5997f267e0Sdan } db2 6097f267e0Sdan} {1 {database table is locked}} 6197f267e0Sdan 6297f267e0Sdan# Verify that the first connection can commit its transaction. 6397f267e0Sdan# 6497f267e0Sdando_test fts3shared-1.4 { sqlite3_get_autocommit db } 0 6597f267e0Sdando_execsql_test fts3shared-1.5 { COMMIT } {} 6697f267e0Sdando_test fts3shared-1.6 { sqlite3_get_autocommit db } 1 6797f267e0Sdan 6897f267e0Sdan# Verify that the second connection still has an open transaction. 6997f267e0Sdan# 7097f267e0Sdando_test fts3shared-1.6 { sqlite3_get_autocommit db2 } 0 7197f267e0Sdan 7297f267e0Sdandb close 7397f267e0Sdandb2 close 7497f267e0Sdan 75*87ddfeb0Sdan#------------------------------------------------------------------------- 76*87ddfeb0Sdan# The following tests - fts3shared-2.* - test that unless FTS is bypassed 77*87ddfeb0Sdan# and the underlying tables accessed directly, it is not possible for an 78*87ddfeb0Sdan# SQLITE_LOCKED error to be enountered when committing an FTS transaction. 79*87ddfeb0Sdan# 80*87ddfeb0Sdan# Any SQLITE_LOCKED error should be returned when the fts4 (or fts4aux) 81*87ddfeb0Sdan# table is first read/written within a transaction, not later on. 82*87ddfeb0Sdan# 83*87ddfeb0Sdanset LOCKED {1 {database table is locked}} 84*87ddfeb0Sdanforcedelete test.db 85*87ddfeb0Sdansqlite3 dbR test.db 86*87ddfeb0Sdansqlite3 dbW test.db 87*87ddfeb0Sdando_test 2.1 { 88*87ddfeb0Sdan execsql { 89*87ddfeb0Sdan CREATE VIRTUAL TABLE t1 USING fts4; 90*87ddfeb0Sdan CREATE TABLE t2ext(a, b); 91*87ddfeb0Sdan CREATE VIRTUAL TABLE t2 USING fts4(content=t2ext); 92*87ddfeb0Sdan CREATE VIRTUAL TABLE t1aux USING fts4aux(t1); 93*87ddfeb0Sdan CREATE VIRTUAL TABLE t2aux USING fts4aux(t2); 94*87ddfeb0Sdan 95*87ddfeb0Sdan INSERT INTO t1 VALUES('a b c'); 96*87ddfeb0Sdan INSERT INTO t2(rowid, a, b) VALUES(1, 'd e f', 'g h i'); 97*87ddfeb0Sdan } dbW 98*87ddfeb0Sdan} {} 99*87ddfeb0Sdan 100*87ddfeb0Sdan# Test that once [dbW] has written to the FTS table, no client may read 101*87ddfeb0Sdan# from the FTS or fts4aux table. 102*87ddfeb0Sdando_test 2.2.1 { 103*87ddfeb0Sdan execsql { 104*87ddfeb0Sdan BEGIN; 105*87ddfeb0Sdan INSERT INTO t1 VALUES('j k l'); 106*87ddfeb0Sdan } dbW 107*87ddfeb0Sdan execsql BEGIN dbR 108*87ddfeb0Sdan} {} 109*87ddfeb0Sdando_test 2.2.2 { catchsql "SELECT * FROM t1 WHERE rowid=1" dbR } $LOCKED 110*87ddfeb0Sdando_test 2.2.3 { catchsql "SELECT * FROM t1 WHERE t1 MATCH 'a'" dbR } $LOCKED 111*87ddfeb0Sdando_test 2.2.4 { catchsql "SELECT rowid FROM t1 WHERE t1 MATCH 'a'" dbR } $LOCKED 112*87ddfeb0Sdando_test 2.2.5 { catchsql "SELECT * FROM t1" dbR } $LOCKED 113*87ddfeb0Sdando_test 2.2.6 { catchsql "SELECT * FROM t1aux" dbR } $LOCKED 114*87ddfeb0Sdando_test 2.2.7 { execsql COMMIT dbW } {} 115*87ddfeb0Sdando_test 2.2.8 { execsql COMMIT dbR } {} 116*87ddfeb0Sdan 117*87ddfeb0Sdan# Same test as 2.2.*, except with a content= table. 118*87ddfeb0Sdan# 119*87ddfeb0Sdando_test 2.3.1 { 120*87ddfeb0Sdan execsql { 121*87ddfeb0Sdan BEGIN; 122*87ddfeb0Sdan INSERT INTO t2(rowid, a, b) VALUES(2, 'j k l', 'm n o'); 123*87ddfeb0Sdan } dbW 124*87ddfeb0Sdan execsql BEGIN dbR 125*87ddfeb0Sdan} {} 126*87ddfeb0Sdando_test 2.3.3 { catchsql "SELECT * FROM t2 WHERE t2 MATCH 'a'" dbR } $LOCKED 127*87ddfeb0Sdando_test 2.3.4 { catchsql "SELECT rowid FROM t2 WHERE t2 MATCH 'a'" dbR } $LOCKED 128*87ddfeb0Sdando_test 2.3.6 { catchsql "SELECT * FROM t2aux" dbR } $LOCKED 129*87ddfeb0Sdando_test 2.3.7 { execsql COMMIT dbW } {} 130*87ddfeb0Sdando_test 2.3.8 { execsql COMMIT dbR } {} 131*87ddfeb0Sdan 132*87ddfeb0Sdan# Test that once a connection has read from the FTS or fts4aux table, 133*87ddfeb0Sdan# another connection may not write to the FTS table. 134*87ddfeb0Sdan# 135*87ddfeb0Sdanforeach {tn sql} { 136*87ddfeb0Sdan 1 "SELECT * FROM t1 WHERE rowid=1" 137*87ddfeb0Sdan 2 "SELECT * FROM t1 WHERE t1 MATCH 'a'" 138*87ddfeb0Sdan 3 "SELECT rowid FROM t1 WHERE t1 MATCH 'a'" 139*87ddfeb0Sdan 4 "SELECT * FROM t1" 140*87ddfeb0Sdan 5 "SELECT * FROM t1aux" 141*87ddfeb0Sdan} { 142*87ddfeb0Sdan 143*87ddfeb0Sdan do_test 2.4.$tn { 144*87ddfeb0Sdan execsql BEGIN dbR 145*87ddfeb0Sdan execsql $::sql dbR 146*87ddfeb0Sdan execsql BEGIN dbW 147*87ddfeb0Sdan catchsql "INSERT INTO t1 VALUES('p q r')" dbW 148*87ddfeb0Sdan } $LOCKED 149*87ddfeb0Sdan 150*87ddfeb0Sdan execsql ROLLBACK dbR 151*87ddfeb0Sdan execsql ROLLBACK dbW 152*87ddfeb0Sdan} 153*87ddfeb0Sdan 154*87ddfeb0Sdan# Same test as 2.4.*, except with a content= table. 155*87ddfeb0Sdan# 156*87ddfeb0Sdanforeach {tn sql} { 157*87ddfeb0Sdan 2 "SELECT * FROM t2 WHERE t2 MATCH 'a'" 158*87ddfeb0Sdan 3 "SELECT rowid FROM t2 WHERE t2 MATCH 'a'" 159*87ddfeb0Sdan 5 "SELECT * FROM t2aux" 160*87ddfeb0Sdan} { 161*87ddfeb0Sdan 162*87ddfeb0Sdan do_test 2.5.$tn { 163*87ddfeb0Sdan execsql BEGIN dbR 164*87ddfeb0Sdan execsql $::sql dbR 165*87ddfeb0Sdan execsql BEGIN dbW 166*87ddfeb0Sdan catchsql "INSERT INTO t2(rowid, a, b) VALUES(3, 's t u', 'v w x')" dbW 167*87ddfeb0Sdan } $LOCKED 168*87ddfeb0Sdan 169*87ddfeb0Sdan execsql ROLLBACK dbR 170*87ddfeb0Sdan execsql ROLLBACK dbW 171*87ddfeb0Sdan} 172*87ddfeb0Sdan 173*87ddfeb0SdandbW close 174*87ddfeb0SdandbR close 17597f267e0Sdansqlite3_enable_shared_cache $::enable_shared_cache 17697f267e0Sdanfinish_test 177