15bd270b2Sdanielk1977# 2006 July 25 25bd270b2Sdanielk1977# 35bd270b2Sdanielk1977# The author disclaims copyright to this source code. In place of 45bd270b2Sdanielk1977# a legal notice, here is a blessing: 55bd270b2Sdanielk1977# 65bd270b2Sdanielk1977# May you do good and not evil. 75bd270b2Sdanielk1977# May you find forgiveness for yourself and forgive others. 85bd270b2Sdanielk1977# May you share freely, never taking more than you give. 95bd270b2Sdanielk1977# 105bd270b2Sdanielk1977#*********************************************************************** 115bd270b2Sdanielk1977# This file implements regression tests for SQLite library. The focus 125bd270b2Sdanielk1977# of this test is reading and writing to the database from within a 135bd270b2Sdanielk1977# virtual table xSync() callback. 145bd270b2Sdanielk1977# 1577658e2fSdrh# $Id: vtab7.test,v 1.4 2007/12/04 16:54:53 drh Exp $ 165bd270b2Sdanielk1977 175bd270b2Sdanielk1977set testdir [file dirname $argv0] 185bd270b2Sdanielk1977source $testdir/tester.tcl 195bd270b2Sdanielk1977 205bd270b2Sdanielk1977ifcapable !vtab { 215bd270b2Sdanielk1977 finish_test 225bd270b2Sdanielk1977 return 235bd270b2Sdanielk1977} 245bd270b2Sdanielk1977 255bd270b2Sdanielk1977# Register the echo module. Code inside the echo module appends elements 265bd270b2Sdanielk1977# to the global tcl list variable ::echo_module whenever SQLite invokes 275bd270b2Sdanielk1977# certain module callbacks. This includes the xSync(), xCommit() and 285bd270b2Sdanielk1977# xRollback() callbacks. For each of these callback, two elements are 295bd270b2Sdanielk1977# appended to ::echo_module, as follows: 305bd270b2Sdanielk1977# 315bd270b2Sdanielk1977# Module method Elements appended to ::echo_module 325bd270b2Sdanielk1977# ------------------------------------------------------- 335bd270b2Sdanielk1977# xSync() xSync echo($tablename) 345bd270b2Sdanielk1977# xCommit() xCommit echo($tablename) 355bd270b2Sdanielk1977# xRollback() xRollback echo($tablename) 365bd270b2Sdanielk1977# ------------------------------------------------------- 375bd270b2Sdanielk1977# 385bd270b2Sdanielk1977# In each case, $tablename is replaced by the name of the real table (not 395bd270b2Sdanielk1977# the echo table). By setting up a tcl trace on the ::echo_module variable, 405bd270b2Sdanielk1977# code in this file arranges for a Tcl script to be executed from within 415bd270b2Sdanielk1977# the echo module xSync() callback. 425bd270b2Sdanielk1977# 435bd270b2Sdanielk1977register_echo_module [sqlite3_connection_pointer db] 445bd270b2Sdanielk1977trace add variable ::echo_module write echo_module_trace 455bd270b2Sdanielk1977 465bd270b2Sdanielk1977# This Tcl proc is invoked whenever the ::echo_module variable is written. 475bd270b2Sdanielk1977# 485bd270b2Sdanielk1977proc echo_module_trace {args} { 495bd270b2Sdanielk1977 # Filter out writes to ::echo_module that are not xSync, xCommit or 505bd270b2Sdanielk1977 # xRollback callbacks. 515bd270b2Sdanielk1977 if {[llength $::echo_module] < 2} return 525bd270b2Sdanielk1977 set x [lindex $::echo_module end-1] 535bd270b2Sdanielk1977 if {$x ne "xSync" && $x ne "xCommit" && $x ne "xRollback"} return 545bd270b2Sdanielk1977 555bd270b2Sdanielk1977 regexp {^echo.(.*).$} [lindex $::echo_module end] dummy tablename 565bd270b2Sdanielk1977 # puts "Ladies and gentlemen, an $x on $tablename!" 575bd270b2Sdanielk1977 585bd270b2Sdanielk1977 if {[info exists ::callbacks($x,$tablename)]} { 595bd270b2Sdanielk1977 eval $::callbacks($x,$tablename) 605bd270b2Sdanielk1977 } 615bd270b2Sdanielk1977} 625bd270b2Sdanielk1977 635bd270b2Sdanielk1977# The following tests, vtab7-1.*, test that the trace callback on 645bd270b2Sdanielk1977# ::echo_module is providing the expected tcl callbacks. 655bd270b2Sdanielk1977do_test vtab7-1.1 { 665bd270b2Sdanielk1977 execsql { 675bd270b2Sdanielk1977 CREATE TABLE abc(a, b, c); 685bd270b2Sdanielk1977 CREATE VIRTUAL TABLE abc2 USING echo(abc); 695bd270b2Sdanielk1977 } 705bd270b2Sdanielk1977} {} 715bd270b2Sdanielk1977 725bd270b2Sdanielk1977do_test vtab7-1.2 { 735bd270b2Sdanielk1977 set ::callbacks(xSync,abc) {incr ::counter} 745bd270b2Sdanielk1977 set ::counter 0 755bd270b2Sdanielk1977 execsql { 765bd270b2Sdanielk1977 INSERT INTO abc2 VALUES(1, 2, 3); 775bd270b2Sdanielk1977 } 785bd270b2Sdanielk1977 set ::counter 795bd270b2Sdanielk1977} {1} 805bd270b2Sdanielk1977 815bd270b2Sdanielk1977# Write to an existing database table from within an xSync callback. 825bd270b2Sdanielk1977do_test vtab7-2.1 { 835bd270b2Sdanielk1977 set ::callbacks(xSync,abc) { 845bd270b2Sdanielk1977 execsql {INSERT INTO log VALUES('xSync');} 855bd270b2Sdanielk1977 } 865bd270b2Sdanielk1977 execsql { 875bd270b2Sdanielk1977 CREATE TABLE log(msg); 885bd270b2Sdanielk1977 INSERT INTO abc2 VALUES(4, 5, 6); 895bd270b2Sdanielk1977 SELECT * FROM log; 905bd270b2Sdanielk1977 } 915bd270b2Sdanielk1977} {xSync} 925bd270b2Sdanielk1977do_test vtab7-2.3 { 935bd270b2Sdanielk1977 execsql { 945bd270b2Sdanielk1977 INSERT INTO abc2 VALUES(4, 5, 6); 955bd270b2Sdanielk1977 SELECT * FROM log; 965bd270b2Sdanielk1977 } 975bd270b2Sdanielk1977} {xSync xSync} 985bd270b2Sdanielk1977do_test vtab7-2.4 { 995bd270b2Sdanielk1977 execsql { 1005bd270b2Sdanielk1977 INSERT INTO abc2 VALUES(4, 5, 6); 1015bd270b2Sdanielk1977 SELECT * FROM log; 1025bd270b2Sdanielk1977 } 1035bd270b2Sdanielk1977} {xSync xSync xSync} 1045bd270b2Sdanielk1977 1055bd270b2Sdanielk1977# Create a database table from within xSync callback. 1065bd270b2Sdanielk1977do_test vtab7-2.5 { 1075bd270b2Sdanielk1977 set ::callbacks(xSync,abc) { 1085bd270b2Sdanielk1977 execsql { CREATE TABLE newtab(d, e, f); } 1095bd270b2Sdanielk1977 } 1105bd270b2Sdanielk1977 execsql { 1115bd270b2Sdanielk1977 INSERT INTO abc2 VALUES(1, 2, 3); 1125bd270b2Sdanielk1977 SELECT name FROM sqlite_master ORDER BY name; 1135bd270b2Sdanielk1977 } 1145bd270b2Sdanielk1977} {abc abc2 log newtab} 1155bd270b2Sdanielk1977 1165bd270b2Sdanielk1977# Drop a database table from within xSync callback. 11777658e2fSdrh# This is not allowed. Tables cannot be dropped while 11877658e2fSdrh# any other statement is active. 11977658e2fSdrh# 1205bd270b2Sdanielk1977do_test vtab7-2.6 { 1215bd270b2Sdanielk1977 set ::callbacks(xSync,abc) { 12277658e2fSdrh set ::rc [catchsql { DROP TABLE newtab }] 1235bd270b2Sdanielk1977 } 1245bd270b2Sdanielk1977 execsql { 1255bd270b2Sdanielk1977 INSERT INTO abc2 VALUES(1, 2, 3); 1265bd270b2Sdanielk1977 SELECT name FROM sqlite_master ORDER BY name; 1275bd270b2Sdanielk1977 } 12877658e2fSdrh} {abc abc2 log newtab} 12977658e2fSdrhdo_test vtab7-2.6.1 { 13077658e2fSdrh set ::rc 13177658e2fSdrh} {1 {database table is locked}} 13277658e2fSdrhexecsql {DROP TABLE newtab} 1335bd270b2Sdanielk1977 1345bd270b2Sdanielk1977# Write to an attached database from xSync(). 1355a8f9374Sdanielk1977ifcapable attach { 1365bd270b2Sdanielk1977 do_test vtab7-3.1 { 137fda06befSmistachkin forcedelete test2.db 138fda06befSmistachkin forcedelete test2.db-journal 1395bd270b2Sdanielk1977 execsql { 1405bd270b2Sdanielk1977 ATTACH 'test2.db' AS db2; 1415bd270b2Sdanielk1977 CREATE TABLE db2.stuff(description, shape, color); 1425bd270b2Sdanielk1977 } 1435bd270b2Sdanielk1977 set ::callbacks(xSync,abc) { 1445bd270b2Sdanielk1977 execsql { INSERT INTO db2.stuff VALUES('abc', 'square', 'green'); } 1455bd270b2Sdanielk1977 } 1465bd270b2Sdanielk1977 execsql { 1475bd270b2Sdanielk1977 INSERT INTO abc2 VALUES(1, 2, 3); 1485bd270b2Sdanielk1977 SELECT * from stuff; 1495bd270b2Sdanielk1977 } 1505bd270b2Sdanielk1977 } {abc square green} 1515a8f9374Sdanielk1977} 1525bd270b2Sdanielk1977 1535bd270b2Sdanielk1977# UPDATE: The next test passes, but leaks memory. So leave it out. 1545bd270b2Sdanielk1977# 1555bd270b2Sdanielk1977# The following tests test that writing to the database from within 1565bd270b2Sdanielk1977# the xCommit callback causes a misuse error. 1575bd270b2Sdanielk1977# do_test vtab7-4.1 { 1585bd270b2Sdanielk1977# unset -nocomplain ::callbacks(xSync,abc) 1595bd270b2Sdanielk1977# set ::callbacks(xCommit,abc) { 1605bd270b2Sdanielk1977# execsql { INSERT INTO log VALUES('hello') } 1615bd270b2Sdanielk1977# } 1625bd270b2Sdanielk1977# catchsql { 1635bd270b2Sdanielk1977# INSERT INTO abc2 VALUES(1, 2, 3); 1645bd270b2Sdanielk1977# } 165*ff4fa772Sdrh# } {1 {bad parameter or other API misuse}} 1665bd270b2Sdanielk1977 16720b1eaffSdanielk1977# These tests, vtab7-4.*, test that an SQLITE_LOCKED error is returned 16820b1eaffSdanielk1977# if an attempt to write to a virtual module table or create a new 16920b1eaffSdanielk1977# virtual table from within an xSync() callback. 17020b1eaffSdanielk1977do_test vtab7-4.1 { 17120b1eaffSdanielk1977 execsql { 17220b1eaffSdanielk1977 CREATE TABLE def(d, e, f); 17320b1eaffSdanielk1977 CREATE VIRTUAL TABLE def2 USING echo(def); 17420b1eaffSdanielk1977 } 17520b1eaffSdanielk1977 set ::callbacks(xSync,abc) { 17620b1eaffSdanielk1977 set ::error [catchsql { INSERT INTO def2 VALUES(1, 2, 3) }] 17720b1eaffSdanielk1977 } 17820b1eaffSdanielk1977 execsql { 17920b1eaffSdanielk1977 INSERT INTO abc2 VALUES(1, 2, 3); 18020b1eaffSdanielk1977 } 18120b1eaffSdanielk1977 set ::error 18220b1eaffSdanielk1977} {1 {database table is locked}} 18320b1eaffSdanielk1977do_test vtab7-4.2 { 18420b1eaffSdanielk1977 set ::callbacks(xSync,abc) { 18520b1eaffSdanielk1977 set ::error [catchsql { CREATE VIRTUAL TABLE def3 USING echo(def) }] 18620b1eaffSdanielk1977 } 18720b1eaffSdanielk1977 execsql { 18820b1eaffSdanielk1977 INSERT INTO abc2 VALUES(1, 2, 3); 18920b1eaffSdanielk1977 } 19020b1eaffSdanielk1977 set ::error 19120b1eaffSdanielk1977} {1 {database table is locked}} 19220b1eaffSdanielk1977 19320b1eaffSdanielk1977do_test vtab7-4.3 { 19420b1eaffSdanielk1977 set ::callbacks(xSync,abc) { 19520b1eaffSdanielk1977 set ::error [catchsql { DROP TABLE def2 }] 19620b1eaffSdanielk1977 } 19720b1eaffSdanielk1977 execsql { 19820b1eaffSdanielk1977 INSERT INTO abc2 VALUES(1, 2, 3); 19920b1eaffSdanielk1977 SELECT name FROM sqlite_master ORDER BY name; 20020b1eaffSdanielk1977 } 20120b1eaffSdanielk1977 set ::error 20220b1eaffSdanielk1977} {1 {database table is locked}} 2035bd270b2Sdanielk1977 2045bd270b2Sdanielk1977trace remove variable ::echo_module write echo_module_trace 2055bd270b2Sdanielk1977unset -nocomplain ::callbacks 2065bd270b2Sdanielk1977 2075bd270b2Sdanielk1977finish_test 208