persistentstorage/sqlite3api/TEST/TclScript/vtab7.test
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 # 2006 July 25
       
     2 #
       
     3 # The author disclaims copyright to this source code.  In place of
       
     4 # 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 # This file implements regression tests for SQLite library. The focus
       
    12 # of this test is reading and writing to the database from within a
       
    13 # virtual table xSync() callback.
       
    14 #
       
    15 # $Id: vtab7.test,v 1.4 2007/12/04 16:54:53 drh Exp $
       
    16 
       
    17 set testdir [file dirname $argv0]
       
    18 source $testdir/tester.tcl
       
    19 
       
    20 ifcapable !vtab {
       
    21   finish_test
       
    22   return
       
    23 }
       
    24 
       
    25 # Register the echo module. Code inside the echo module appends elements
       
    26 # to the global tcl list variable ::echo_module whenever SQLite invokes
       
    27 # certain module callbacks. This includes the xSync(), xCommit() and 
       
    28 # xRollback() callbacks. For each of these callback, two elements are
       
    29 # appended to ::echo_module, as follows:
       
    30 #
       
    31 #     Module method        Elements appended to ::echo_module
       
    32 #     -------------------------------------------------------
       
    33 #     xSync()              xSync echo($tablename)
       
    34 #     xCommit()            xCommit echo($tablename)
       
    35 #     xRollback()          xRollback echo($tablename)
       
    36 #     -------------------------------------------------------
       
    37 #
       
    38 # In each case, $tablename is replaced by the name of the real table (not
       
    39 # the echo table). By setting up a tcl trace on the ::echo_module variable,
       
    40 # code in this file arranges for a Tcl script to be executed from within
       
    41 # the echo module xSync() callback.
       
    42 #
       
    43 register_echo_module [sqlite3_connection_pointer db]
       
    44 trace add variable ::echo_module write echo_module_trace
       
    45 
       
    46 # This Tcl proc is invoked whenever the ::echo_module variable is written.
       
    47 #
       
    48 proc echo_module_trace {args} {
       
    49   # Filter out writes to ::echo_module that are not xSync, xCommit or 
       
    50   # xRollback callbacks.
       
    51   if {[llength $::echo_module] < 2} return
       
    52   set x [lindex $::echo_module end-1]
       
    53   if {$x ne "xSync" && $x ne "xCommit" && $x ne "xRollback"} return
       
    54 
       
    55   regexp {^echo.(.*).$} [lindex $::echo_module end] dummy tablename
       
    56   # puts "Ladies and gentlemen, an $x on $tablename!"
       
    57 
       
    58   if {[info exists ::callbacks($x,$tablename)]} {
       
    59     eval $::callbacks($x,$tablename)
       
    60   }
       
    61 }
       
    62 
       
    63 # The following tests, vtab7-1.*, test that the trace callback on 
       
    64 # ::echo_module is providing the expected tcl callbacks.
       
    65 do_test vtab7-1.1 {
       
    66   execsql {
       
    67     CREATE TABLE abc(a, b, c);
       
    68     CREATE VIRTUAL TABLE abc2 USING echo(abc);
       
    69   }
       
    70 } {}
       
    71 
       
    72 do_test vtab7-1.2 {
       
    73   set ::callbacks(xSync,abc) {incr ::counter}
       
    74   set ::counter 0
       
    75   execsql {
       
    76     INSERT INTO abc2 VALUES(1, 2, 3);
       
    77   }
       
    78   set ::counter
       
    79 } {1}
       
    80 
       
    81 # Write to an existing database table from within an xSync callback.
       
    82 do_test vtab7-2.1 {
       
    83   set ::callbacks(xSync,abc) {
       
    84     execsql {INSERT INTO log VALUES('xSync');}
       
    85   }
       
    86   execsql {
       
    87     CREATE TABLE log(msg);
       
    88     INSERT INTO abc2 VALUES(4, 5, 6);
       
    89     SELECT * FROM log;
       
    90   }
       
    91 } {xSync}
       
    92 do_test vtab7-2.3 {
       
    93   execsql {
       
    94     INSERT INTO abc2 VALUES(4, 5, 6);
       
    95     SELECT * FROM log;
       
    96   }
       
    97 } {xSync xSync}
       
    98 do_test vtab7-2.4 {
       
    99   execsql {
       
   100     INSERT INTO abc2 VALUES(4, 5, 6);
       
   101     SELECT * FROM log;
       
   102   }
       
   103 } {xSync xSync xSync}
       
   104 
       
   105 # Create a database table from within xSync callback.
       
   106 do_test vtab7-2.5 {
       
   107   set ::callbacks(xSync,abc) {
       
   108     execsql { CREATE TABLE newtab(d, e, f); }
       
   109   }
       
   110   execsql {
       
   111     INSERT INTO abc2 VALUES(1, 2, 3);
       
   112     SELECT name FROM sqlite_master ORDER BY name;
       
   113   }
       
   114 } {abc abc2 log newtab}
       
   115 
       
   116 # Drop a database table from within xSync callback.
       
   117 # This is not allowed.  Tables cannot be dropped while
       
   118 # any other statement is active.
       
   119 #
       
   120 do_test vtab7-2.6 {
       
   121   set ::callbacks(xSync,abc) {
       
   122     set ::rc [catchsql { DROP TABLE newtab }]
       
   123   }
       
   124   execsql {
       
   125     INSERT INTO abc2 VALUES(1, 2, 3);
       
   126     SELECT name FROM sqlite_master ORDER BY name;
       
   127   }
       
   128 } {abc abc2 log newtab}
       
   129 do_test vtab7-2.6.1 {
       
   130   set ::rc
       
   131 } {1 {database table is locked}}
       
   132 execsql {DROP TABLE newtab}
       
   133 
       
   134 # Write to an attached database from xSync().
       
   135 ifcapable attach {
       
   136   do_test vtab7-3.1 {
       
   137     file delete -force test2.db
       
   138     file delete -force test2.db-journal
       
   139     execsql {
       
   140       ATTACH 'test2.db' AS db2;
       
   141       CREATE TABLE db2.stuff(description, shape, color);
       
   142     }
       
   143     set ::callbacks(xSync,abc) {
       
   144       execsql { INSERT INTO db2.stuff VALUES('abc', 'square', 'green'); }
       
   145     }
       
   146     execsql {
       
   147       INSERT INTO abc2 VALUES(1, 2, 3);
       
   148       SELECT * from stuff;
       
   149     }
       
   150   } {abc square green}
       
   151 }
       
   152 
       
   153 # UPDATE: The next test passes, but leaks memory. So leave it out.
       
   154 #
       
   155 # The following tests test that writing to the database from within
       
   156 # the xCommit callback causes a misuse error.
       
   157 # do_test vtab7-4.1 {
       
   158 #   unset -nocomplain ::callbacks(xSync,abc)
       
   159 #   set ::callbacks(xCommit,abc) {
       
   160 #     execsql { INSERT INTO log VALUES('hello') }
       
   161 #   }
       
   162 #   catchsql {
       
   163 #     INSERT INTO abc2 VALUES(1, 2, 3);
       
   164 #   }
       
   165 # } {1 {library routine called out of sequence}}
       
   166 
       
   167 # These tests, vtab7-4.*, test that an SQLITE_LOCKED error is returned
       
   168 # if an attempt to write to a virtual module table or create a new 
       
   169 # virtual table from within an xSync() callback.
       
   170 do_test vtab7-4.1 {
       
   171   execsql {
       
   172     CREATE TABLE def(d, e, f);
       
   173     CREATE VIRTUAL TABLE def2 USING echo(def);
       
   174   }
       
   175   set ::callbacks(xSync,abc) {
       
   176     set ::error [catchsql { INSERT INTO def2 VALUES(1, 2, 3) }]
       
   177   }
       
   178   execsql {
       
   179     INSERT INTO abc2 VALUES(1, 2, 3);
       
   180   }
       
   181   set ::error
       
   182 } {1 {database table is locked}}
       
   183 do_test vtab7-4.2 {
       
   184   set ::callbacks(xSync,abc) {
       
   185     set ::error [catchsql { CREATE VIRTUAL TABLE def3 USING echo(def) }]
       
   186   }
       
   187   execsql {
       
   188     INSERT INTO abc2 VALUES(1, 2, 3);
       
   189   }
       
   190   set ::error
       
   191 } {1 {database table is locked}}
       
   192 
       
   193 do_test vtab7-4.3 {
       
   194   set ::callbacks(xSync,abc) {
       
   195     set ::error [catchsql { DROP TABLE def2 }]
       
   196   }
       
   197   execsql {
       
   198     INSERT INTO abc2 VALUES(1, 2, 3);
       
   199     SELECT name FROM sqlite_master ORDER BY name;
       
   200   }
       
   201   set ::error
       
   202 } {1 {database table is locked}}
       
   203 
       
   204 trace remove variable ::echo_module write echo_module_trace
       
   205 unset -nocomplain ::callbacks
       
   206 
       
   207 finish_test