gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/vtab1.test (about)

     1  # 2006 June 10
     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
    12  # focus of this file is creating and dropping virtual tables.
    13  #
    14  # $Id: vtab1.test,v 1.57 2008/08/01 17:51:47 danielk1977 Exp $
    15  
    16  set testdir [file dirname $argv0]
    17  source $testdir/tester.tcl
    18  set testprefix vtab1
    19  
    20  ifcapable !vtab||!schema_pragmas {
    21    finish_test
    22    return
    23  }
    24  
    25  #----------------------------------------------------------------------
    26  # Organization of tests in this file:
    27  #
    28  # vtab1-1.*: Error conditions and other issues surrounding creation/connection
    29  #            of a virtual module.
    30  # vtab1-2.*: Test sqlite3_declare_vtab() and the xConnect/xDisconnect methods.
    31  # vtab1-3.*: Table scans and WHERE clauses.
    32  # vtab1-4.*: Table scans and ORDER BY clauses.
    33  # vtab1-5.*: Test queries that include joins. This brings the
    34  #            sqlite3_index_info.estimatedCost variable into play.
    35  # vtab1-6.*: Test UPDATE/INSERT/DELETE on vtables.
    36  # vtab1-7.*: Test sqlite3_last_insert_rowid().
    37  #
    38  # This file uses the "echo" module (see src/test8.c). Refer to comments
    39  # in that file for the special behaviour of the Tcl $echo_module variable.
    40  #
    41  # TODO: 
    42  #   * How to test the sqlite3_index_constraint_usage.omit field?
    43  #   * vtab1-5.*
    44  #
    45  # vtab1-14.*: Test 'IN' constraints - i.e. "SELECT * FROM t1 WHERE id IN(...)"
    46  #
    47  # vtab1-18.*: Check that the LIKE optimization is not applied when the lhs
    48  #             is a virtual table column.
    49  #
    50  
    51  
    52  #----------------------------------------------------------------------
    53  # Test cases vtab1.1.*
    54  #
    55  
    56  # We cannot create a virtual table if the module has not been registered.
    57  #
    58  do_test vtab1-1.1.1 {
    59    catchsql {
    60      CREATE VIRTUAL TABLE t1 USING echo;
    61    }
    62  } {1 {no such module: echo}}
    63  do_test vtab1-1.1.2 {
    64    catchsql {
    65      CREATE VIRTUAL TABLE IF NOT EXISTS t1 USING echo;
    66    }
    67  } {1 {no such module: echo}}
    68  do_test vtab1-1.2 {
    69    execsql {
    70      SELECT name FROM sqlite_master ORDER BY 1
    71    }
    72  } {}
    73  
    74  # Register the module
    75  register_echo_module [sqlite3_connection_pointer db]
    76  
    77  # Once a module has been registered, virtual tables using that module
    78  # may be created. However if a module xCreate() fails to call
    79  # sqlite3_declare_vtab() an error will be raised and the table not created.
    80  #
    81  # The "echo" module does not invoke sqlite3_declare_vtab() if it is
    82  # passed zero arguments.
    83  #
    84  do_test vtab1-1.3.1 {
    85    catchsql {
    86      CREATE VIRTUAL TABLE t1 USING echo;
    87    }
    88  } {1 {vtable constructor did not declare schema: t1}}
    89  do_test vtab1-1.3.2 {
    90    catchsql {
    91      CREATE VIRTUAL TABLE IF NOT EXISTS t1 USING echo;
    92    }
    93  } {1 {vtable constructor did not declare schema: t1}}
    94  do_test vtab1-1.4 {
    95    execsql {
    96      SELECT name FROM sqlite_master ORDER BY 1
    97    }
    98  } {}
    99  
   100  # The "echo" module xCreate method returns an error and does not create
   101  # the virtual table if it is passed an argument that does not correspond
   102  # to an existing real table in the same database.
   103  #
   104  do_test vtab1-1.5.1 {
   105    catchsql {
   106      CREATE VIRTUAL TABLE t1 USING echo(no_such_table);
   107    }
   108  } {1 {vtable constructor failed: t1}}
   109  do_test vtab1-1.5.2 {
   110    catchsql {
   111      CREATE VIRTUAL TABLE IF NOT EXISTS t1 USING echo(no_such_table);
   112    }
   113  } {1 {vtable constructor failed: t1}}
   114  do_test vtab1-1.6 {
   115    execsql {
   116      SELECT name FROM sqlite_master ORDER BY 1
   117    }
   118  } {}
   119  
   120  # Ticket #2156.  Using the sqlite3_prepare_v2() API, make sure that
   121  # a CREATE VIRTUAL TABLE statement can be used multiple times.
   122  #
   123  do_test vtab1-1.2152.1 {
   124    set DB [sqlite3_connection_pointer db]
   125    set sql {CREATE VIRTUAL TABLE t2152a USING echo(t2152b)}
   126    set STMT [sqlite3_prepare_v2 $DB $sql -1 TAIL]
   127    sqlite3_step $STMT
   128  } SQLITE_ERROR
   129  do_test vtab-1.2152.2 {
   130    sqlite3_reset $STMT
   131    sqlite3_step $STMT
   132  } SQLITE_ERROR
   133  do_test vtab-1.2152.3 {
   134    sqlite3_reset $STMT
   135    db eval {CREATE TABLE t2152b(x,y)}
   136    sqlite3_step $STMT
   137  } SQLITE_DONE
   138  do_test vtab-1.2152.4 {
   139    sqlite3_finalize $STMT
   140    db eval {DROP TABLE t2152a; DROP TABLE t2152b}
   141  } {}
   142  
   143  # Test to make sure nothing goes wrong and no memory is leaked if we 
   144  # select an illegal table-name (i.e a reserved name or the name of a
   145  # table that already exists).
   146  #
   147  do_test vtab1-1.7.1 {
   148    catchsql {
   149      CREATE VIRTUAL TABLE sqlite_master USING echo;
   150    }
   151  } {1 {object name reserved for internal use: sqlite_master}}
   152  do_test vtab1-1.7.2 {
   153    catchsql {
   154      CREATE VIRTUAL TABLE IF NOT EXISTS sqlite_master USING echo;
   155    }
   156  } {1 {object name reserved for internal use: sqlite_master}}
   157  do_test vtab1-1.8.1 {
   158    catchsql {
   159      CREATE TABLE treal(a, b, c);
   160      CREATE VIRTUAL TABLE treal USING echo(treal);
   161    }
   162  } {1 {table treal already exists}}
   163  do_test vtab1-1.8.2 {
   164    catchsql {
   165      CREATE VIRTUAL TABLE IF NOT EXISTS treal USING echo(treal);
   166    }
   167  } {0 {}}
   168  do_test vtab1-1.9 {
   169    execsql {
   170      DROP TABLE treal;
   171      SELECT name FROM sqlite_master ORDER BY 1
   172    }
   173  } {}
   174  
   175  do_test vtab1-1.10 {
   176    execsql {
   177      CREATE TABLE treal(a, b, c);
   178      CREATE VIRTUAL TABLE techo USING echo(treal);
   179    }
   180    db close
   181    sqlite3 db test.db
   182    catchsql {
   183      SELECT * FROM techo;
   184    }
   185  } {1 {no such module: echo}}
   186  do_test vtab1-1.11 {
   187    catchsql {
   188      INSERT INTO techo VALUES(1, 2, 3);
   189    }
   190  } {1 {no such module: echo}}
   191  do_test vtab1-1.12 {
   192    catchsql {
   193      UPDATE techo SET a = 10;
   194    }
   195  } {1 {no such module: echo}}
   196  do_test vtab1-1.13 {
   197    catchsql {
   198      DELETE FROM techo;
   199    }
   200  } {1 {no such module: echo}}
   201  do_test vtab1-1.14 {
   202    catchsql {
   203      PRAGMA table_info(techo)
   204    }
   205  } {1 {no such module: echo}}
   206  do_test vtab1-1.15 {
   207    catchsql {
   208      DROP TABLE techo;
   209    }
   210  } {1 {no such module: echo}}
   211  
   212  register_echo_module [sqlite3_connection_pointer db]
   213  register_echo_module [sqlite3_connection_pointer db]
   214  
   215  # Test an error message returned from a v-table constructor.
   216  #
   217  do_test vtab1-1.16 {
   218    execsql {
   219      DROP TABLE techo;
   220      CREATE TABLE logmsg(log);
   221    }
   222    catchsql {
   223      CREATE VIRTUAL TABLE techo USING echo(treal, logmsg);
   224    }
   225  } {1 {table 'logmsg' already exists}}
   226  
   227  do_test vtab1-1.17 {
   228    execsql {
   229      DROP TABLE treal;
   230      DROP TABLE logmsg;
   231      SELECT sql FROM sqlite_master;
   232    }
   233  } {}
   234  
   235  #----------------------------------------------------------------------
   236  # Test cases vtab1.2.*
   237  #
   238  # At this point, the database is completely empty. The echo module
   239  # has already been registered.
   240  
   241  # If a single argument is passed to the echo module during table
   242  # creation, it is assumed to be the name of a table in the same
   243  # database. The echo module attempts to set the schema of the
   244  # new virtual table to be the same as the existing database table.
   245  #
   246  do_test vtab1-2.1 {
   247    execsql {
   248      CREATE TABLE template(a, b, c);
   249    }
   250    execsql { PRAGMA table_info(template); }
   251  } [list         \
   252    0 a {} 0 {} 0 \
   253    1 b {} 0 {} 0 \
   254    2 c {} 0 {} 0 \
   255  ]
   256  do_test vtab1-2.2 {
   257    execsql {
   258      CREATE VIRTUAL TABLE t1 USING echo(template);
   259    }
   260    execsql { PRAGMA table_info(t1); }
   261  } [list         \
   262    0 a {} 0 {} 0 \
   263    1 b {} 0 {} 0 \
   264    2 c {} 0 {} 0 \
   265  ]
   266  
   267  # Test that the database can be unloaded. This should invoke the xDisconnect()
   268  # callback for the successfully create virtual table (t1).
   269  #
   270  do_test vtab1-2.3 {
   271    set echo_module [list]
   272    db close
   273    set echo_module
   274  } [list xDisconnect]
   275  
   276  # Re-open the database. This should not cause any virtual methods to 
   277  # be called. The invocation of xConnect() is delayed until the virtual
   278  # table schema is first required by the compiler.
   279  #
   280  do_test vtab1-2.4 {
   281    set echo_module [list]
   282    sqlite3 db test.db
   283    db cache size 0
   284    set echo_module
   285  } {}
   286  
   287  # Try to query the virtual table schema. This should fail, as the
   288  # echo module has not been registered with this database connection.
   289  #
   290  do_test vtab1.2.6 {
   291    catchsql { PRAGMA table_info(t1); }
   292  } {1 {no such module: echo}}
   293  
   294  # Register the module
   295  register_echo_module [sqlite3_connection_pointer db]
   296  
   297  # Try to query the virtual table schema again. This time it should
   298  # invoke the xConnect method and succeed.
   299  #
   300  do_test vtab1.2.7 {
   301    execsql { PRAGMA table_info(t1); }
   302  } [list         \
   303    0 a {} 0 {} 0 \
   304    1 b {} 0 {} 0 \
   305    2 c {} 0 {} 0 \
   306  ]
   307  do_test vtab1.2.8 {
   308    set echo_module
   309  } {xConnect echo main t1 template}
   310  
   311  # Drop table t1. This should cause the xDestroy (but not xDisconnect) method 
   312  # to be invoked.
   313  do_test vtab1-2.5 {
   314    set echo_module ""
   315    execsql {
   316      DROP TABLE t1;
   317    }
   318    set echo_module
   319  } {xDestroy}
   320  
   321  do_test vtab1-2.6 {
   322    execsql { 
   323      PRAGMA table_info(t1); 
   324    }
   325  } {}
   326  do_test vtab1-2.7 {
   327    execsql {
   328      SELECT sql FROM sqlite_master;
   329    }
   330  } [list {CREATE TABLE template(a, b, c)}]
   331  # Clean up other test artifacts:
   332  do_test vtab1-2.8 {
   333    execsql { 
   334      DROP TABLE template;
   335      SELECT sql FROM sqlite_master;
   336    }
   337  } [list]
   338  
   339  #----------------------------------------------------------------------
   340  # Test case vtab1-3 test table scans and the echo module's 
   341  # xBestIndex/xFilter handling of WHERE conditions.
   342  
   343  do_test vtab1-3.1 {
   344    set echo_module ""
   345    execsql {
   346      CREATE TABLE treal(a INTEGER, b INTEGER, c); 
   347      CREATE INDEX treal_idx ON treal(b);
   348      CREATE VIRTUAL TABLE t1 USING echo(treal);
   349    }
   350    set echo_module
   351  } [list xCreate echo main t1 treal   \
   352          xSync   echo(treal)  \
   353          xCommit echo(treal)  \
   354  ]
   355  
   356  # Test that a SELECT on t1 doesn't crash. No rows are returned
   357  # because the underlying real table is currently empty.
   358  #
   359  do_test vtab1-3.2 {
   360    execsql {
   361      SELECT a, b, c FROM t1;
   362    }
   363  } {}
   364  
   365  # Put some data into the table treal. Then try a few simple SELECT 
   366  # statements on t1.
   367  #
   368  do_test vtab1-3.3 {
   369    execsql {
   370      INSERT INTO treal VALUES(1, 2, 3);
   371      INSERT INTO treal VALUES(4, 5, 6);
   372      SELECT * FROM t1;
   373    }
   374  } {1 2 3 4 5 6}
   375  do_test vtab1-3.4 {
   376    execsql {
   377      SELECT a FROM t1;
   378    }
   379  } {1 4}
   380  do_test vtab1-3.5 {
   381    execsql {
   382      SELECT rowid FROM t1;
   383    }
   384  } {1 2}
   385  do_test vtab1-3.6 {
   386    set echo_module ""
   387    execsql {
   388      SELECT * FROM t1;
   389    }
   390  } {1 2 3 4 5 6}
   391  do_test vtab1-3.7 {
   392    execsql {
   393      SELECT rowid, * FROM t1;
   394    }
   395  } {1 1 2 3 2 4 5 6}
   396  do_test vtab1-3.8.1 {
   397    execsql {
   398      SELECT a AS d, b AS e, c AS f FROM t1;
   399    }
   400  } {1 2 3 4 5 6}
   401  
   402  # Execute some SELECT statements with WHERE clauses on the t1 table.
   403  # Then check the echo_module variable (written to by the module methods
   404  # in test8.c) to make sure the xBestIndex() and xFilter() methods were
   405  # called correctly.
   406  #
   407  do_test vtab1-3.8.2 {
   408    set echo_module ""
   409    execsql {
   410      SELECT * FROM t1;
   411    }
   412    set echo_module
   413  } [list xBestIndex {SELECT rowid, a, b, c FROM 'treal'} \
   414          xFilter    {SELECT rowid, a, b, c FROM 'treal'} ]
   415  do_test vtab1-3.9 {
   416    set echo_module ""
   417    execsql {
   418      SELECT * FROM t1 WHERE b = 5;
   419    }
   420  } {4 5 6}
   421  do_test vtab1-3.10 {
   422    set echo_module
   423  } [list xBestIndex {SELECT rowid, a, b, c FROM 'treal' WHERE b = ?}   \
   424          xFilter    {SELECT rowid, a, b, c FROM 'treal' WHERE b = ?} 5 ]
   425  do_test vtab1-3.10 {
   426    set echo_module ""
   427    execsql {
   428      SELECT * FROM t1 WHERE b >= 5 AND b <= 10;
   429    }
   430  } {4 5 6}
   431  do_test vtab1-3.11 {
   432    set echo_module
   433  } [list xBestIndex {SELECT rowid, a, b, c FROM 'treal' WHERE b >= ? AND b <= ?}\
   434          xFilter    {SELECT rowid, a, b, c FROM 'treal' WHERE b >= ? AND b <= ?}\
   435          5 10 ]
   436  do_test vtab1-3.12 {
   437    set echo_module ""
   438    execsql {
   439      SELECT * FROM t1 WHERE b BETWEEN 2 AND 10;
   440    }
   441  } {1 2 3 4 5 6}
   442  do_test vtab1-3.13 {
   443    set echo_module
   444  } [list xBestIndex {SELECT rowid, a, b, c FROM 'treal' WHERE b >= ? AND b <= ?}\
   445          xFilter    {SELECT rowid, a, b, c FROM 'treal' WHERE b >= ? AND b <= ?}\
   446          2 10 ]
   447  
   448  # Add a function for the MATCH operator. Everything always matches!
   449  #proc test_match {lhs rhs} {
   450  #  lappend ::echo_module MATCH $lhs $rhs
   451  #  return 1
   452  #}
   453  #db function match test_match
   454  
   455  set echo_module ""
   456  do_test vtab1-3.12 {
   457    set echo_module ""
   458    catchsql {
   459      SELECT * FROM t1 WHERE a MATCH 'string';
   460    }
   461  } {1 {unable to use function MATCH in the requested context}}
   462  do_test vtab1-3.13 {
   463    set echo_module
   464  } [list xBestIndex {SELECT rowid, a, b, c FROM 'treal'} \
   465          xFilter    {SELECT rowid, a, b, c FROM 'treal'}]
   466  ifcapable subquery {
   467  # The echo module uses a subquery internally to implement the MATCH operator.
   468  do_test vtab1-3.14 {
   469    set echo_module ""
   470    execsql {
   471      SELECT * FROM t1 WHERE b MATCH 'string';
   472    }
   473  } {}
   474  do_test vtab1-3.15 {
   475    set echo_module
   476  } [list xBestIndex \
   477          {SELECT rowid, a, b, c FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')} \
   478          xFilter \
   479          {SELECT rowid, a, b, c FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')} \
   480          string ]
   481  }; #ifcapable subquery
   482  
   483  #----------------------------------------------------------------------
   484  # Test case vtab1-3 test table scans and the echo module's 
   485  # xBestIndex/xFilter handling of ORDER BY clauses.
   486  
   487  # This procedure executes the SQL.  Then it checks to see if the OP_Sort
   488  # opcode was executed.  If an OP_Sort did occur, then "sort" is appended
   489  # to the result.  If no OP_Sort happened, then "nosort" is appended.
   490  #
   491  # This procedure is used to check to make sure sorting is or is not
   492  # occurring as expected.
   493  #
   494  proc cksort {sql} {
   495    set ::sqlite_sort_count 0
   496    set data [execsql $sql]
   497    if {$::sqlite_sort_count} {set x sort} {set x nosort}
   498    lappend data $x
   499    return $data
   500  }
   501  
   502  do_test vtab1-4.1 {
   503    set echo_module ""
   504    cksort {
   505      SELECT b FROM t1 ORDER BY b;
   506    }
   507  } {2 5 nosort}
   508  do_test vtab1-4.2 {
   509    set echo_module
   510  } [list xBestIndex {SELECT rowid, NULL, b, NULL FROM 'treal' ORDER BY b ASC} \
   511          xFilter    {SELECT rowid, NULL, b, NULL FROM 'treal' ORDER BY b ASC} ]
   512  do_test vtab1-4.3 {
   513    set echo_module ""
   514    cksort {
   515      SELECT b FROM t1 ORDER BY b DESC;
   516    }
   517  } {5 2 nosort}
   518  do_test vtab1-4.4 {
   519    set echo_module
   520  } [list xBestIndex {SELECT rowid, NULL, b, NULL FROM 'treal' ORDER BY b DESC} \
   521          xFilter    {SELECT rowid, NULL, b, NULL FROM 'treal' ORDER BY b DESC} ]
   522  do_test vtab1-4.3 {
   523    set echo_module ""
   524    cksort {
   525      SELECT b FROM t1 ORDER BY b||'';
   526    }
   527  } {2 5 sort}
   528  do_test vtab1-4.4 {
   529    set echo_module
   530  } [list xBestIndex {SELECT rowid, NULL, b, NULL FROM 'treal'} \
   531          xFilter    {SELECT rowid, NULL, b, NULL FROM 'treal'} ]
   532  
   533  execsql {
   534    DROP TABLE t1;
   535    DROP TABLE treal;
   536  }
   537  
   538  #----------------------------------------------------------------------
   539  # Test cases vtab1-5 test SELECT queries that include joins on virtual 
   540  # tables.
   541  
   542  proc filter {log} {
   543    set out [list]
   544    for {set ii 0} {$ii < [llength $log]} {incr ii} {
   545      if {[lindex $log $ii] eq "xFilter"} {
   546        lappend out xFilter
   547        lappend out [lindex $log [expr $ii+1]]
   548      }
   549    }
   550    return $out
   551  }
   552  
   553  do_test vtab1-5-1 {
   554    execsql { 
   555      CREATE TABLE t1(a, b, c);
   556      CREATE TABLE t2(d, e, f);
   557      INSERT INTO t1 VALUES(1, 'red', 'green');
   558      INSERT INTO t1 VALUES(2, 'blue', 'black');
   559      INSERT INTO t2 VALUES(1, 'spades', 'clubs');
   560      INSERT INTO t2 VALUES(2, 'hearts', 'diamonds');
   561      CREATE VIRTUAL TABLE et1 USING echo(t1);
   562      CREATE VIRTUAL TABLE et2 USING echo(t2);
   563    }
   564  } {}
   565  
   566  do_test vtab1-5-2 {
   567    set echo_module ""
   568    execsql {
   569      SELECT * FROM et1, et2;
   570    }
   571  } [list \
   572    1 red green 1 spades clubs     \
   573    1 red green 2 hearts diamonds  \
   574    2 blue black 1 spades clubs    \
   575    2 blue black 2 hearts diamonds \
   576  ]
   577  do_test vtab1-5-3 {
   578    filter $echo_module
   579  } [list \
   580    xFilter {SELECT rowid, a, b, c FROM 't1'} \
   581    xFilter {SELECT rowid, d, e, f FROM 't2'} \
   582    xFilter {SELECT rowid, d, e, f FROM 't2'} \
   583  ]
   584  do_test vtab1-5-4 {
   585    set echo_module ""
   586    execsql {
   587      SELECT * FROM et1, et2 WHERE et2.d = 2;
   588    }
   589  } [list \
   590    1 red green 2 hearts diamonds  \
   591    2 blue black 2 hearts diamonds \
   592  ]
   593  do_test vtab1-5-5 {
   594    filter $echo_module
   595  } [list \
   596    xFilter {SELECT rowid, a, b, c FROM 't1'} \
   597    xFilter {SELECT rowid, d, e, f FROM 't2'} \
   598    xFilter {SELECT rowid, d, e, f FROM 't2'} \
   599  ]
   600  do_test vtab1-5-6 {
   601    execsql {
   602      CREATE INDEX i1 ON t2(d);
   603    }
   604  
   605    db close
   606    sqlite3 db test.db
   607    register_echo_module [sqlite3_connection_pointer db]
   608  
   609    set ::echo_module ""
   610    execsql {
   611      SELECT * FROM et1, et2 WHERE et2.d = 2;
   612    }
   613  } [list \
   614    1 red green 2 hearts diamonds  \
   615    2 blue black 2 hearts diamonds \
   616  ]
   617  do_test vtab1-5-7 {
   618    filter $::echo_module
   619  } [list \
   620    xFilter {SELECT rowid, a, b, c FROM 't1'}             \
   621    xFilter {SELECT rowid, d, e, f FROM 't2' WHERE d = ?} \
   622    xFilter {SELECT rowid, d, e, f FROM 't2' WHERE d = ?} \
   623  ]
   624  
   625  execsql {
   626    DROP TABLE t1;
   627    DROP TABLE t2;
   628    DROP TABLE et1;
   629    DROP TABLE et2;
   630  }
   631  
   632  #----------------------------------------------------------------------
   633  # Test cases vtab1-6 test INSERT, UPDATE and DELETE operations 
   634  # on virtual tables.
   635  do_test vtab1-6-1 {
   636    execsql { SELECT sql FROM sqlite_master }
   637  } {}
   638  do_test vtab1-6-2 {
   639    execsql {
   640      CREATE TABLE treal(a PRIMARY KEY, b, c);
   641      CREATE VIRTUAL TABLE techo USING echo(treal);
   642      SELECT name FROM sqlite_master WHERE type = 'table';
   643    }
   644  } {treal techo}
   645  do_test vtab1-6-3.1.1 {
   646    execsql {
   647      PRAGMA count_changes=ON;
   648      INSERT INTO techo VALUES(1, 2, 3);
   649    }
   650  } {1}
   651  do_test vtab1-6-3.1.2 {
   652    db changes
   653  } {1}
   654  do_test vtab1-6-3.2 {
   655    execsql {
   656      SELECT * FROM techo;
   657    }
   658  } {1 2 3}
   659  do_test vtab1-6-4.1 {
   660    execsql {
   661      UPDATE techo SET a = 5;
   662    }
   663    db changes
   664  } {1}
   665  do_test vtab1-6-4.2 {
   666    execsql {
   667      SELECT * FROM techo;
   668    }
   669  } {5 2 3}
   670  do_test vtab1-6-4.3 {
   671    execsql {
   672      UPDATE techo SET a=6 WHERE a<0;
   673    }
   674    db changes
   675  } {0}
   676  do_test vtab1-6-4.4 {
   677    execsql {
   678      SELECT * FROM techo;
   679    }
   680  } {5 2 3}
   681  
   682  do_test vtab1-6-5.1 {
   683   execsql {
   684     UPDATE techo set a = a||b||c;
   685   }
   686   db changes
   687  } {1}
   688  do_test vtab1-6-5.2 {
   689   execsql {
   690     SELECT * FROM techo;
   691   }
   692  } {523 2 3}
   693  
   694  do_test vtab1-6-6.1 {
   695    execsql {
   696      UPDATE techo set rowid = 10;
   697    }
   698    db changes
   699  } {1}
   700  do_test vtab1-6-6.2 {
   701    execsql {
   702      SELECT rowid FROM techo;
   703    }
   704  } {10}
   705  
   706  do_test vtab1-6-7.1.1 {
   707    execsql {
   708      INSERT INTO techo VALUES(11,12,13);
   709    }
   710  } {1}
   711  do_test vtab1-6-7.1.2 {
   712    db changes
   713  } {1}
   714  do_test vtab1-6-7.2 {
   715    execsql {
   716      SELECT * FROM techo ORDER BY a;
   717    }
   718  } {11 12 13 523 2 3}
   719  do_test vtab1-6-7.3 {
   720    execsql {
   721      UPDATE techo SET b=b+1000
   722    }
   723    db changes
   724  } {2}
   725  do_test vtab1-6-7.4 {
   726    execsql {
   727      SELECT * FROM techo ORDER BY a;
   728    }
   729  } {11 1012 13 523 1002 3}
   730  
   731  
   732  do_test vtab1-6-8.1 {
   733    execsql {
   734      DELETE FROM techo WHERE a=5;
   735    }
   736    db changes
   737  } {0}
   738  do_test vtab1-6-8.2 {
   739    execsql {
   740      SELECT * FROM techo ORDER BY a;
   741    }
   742  } {11 1012 13 523 1002 3}
   743  do_test vtab1-6-8.3 {
   744    execsql {
   745      DELETE FROM techo;
   746    }
   747    db changes
   748  } {2}
   749  do_test vtab1-6-8.4 {
   750    execsql {
   751      SELECT * FROM techo ORDER BY a;
   752    }
   753  } {}
   754  execsql {PRAGMA count_changes=OFF}
   755  
   756  forcedelete test2.db
   757  forcedelete test2.db-journal
   758  sqlite3 db2 test2.db
   759  execsql {
   760    CREATE TABLE techo(a PRIMARY KEY, b, c);
   761  } db2
   762  proc check_echo_table {tn} {
   763    set ::data1 [execsql {SELECT rowid, * FROM techo}]
   764    set ::data2 [execsql {SELECT rowid, * FROM techo} db2]
   765    do_test $tn {
   766      string equal $::data1 $::data2
   767    } 1
   768  }
   769  set tn 0
   770  foreach stmt [list \
   771    {INSERT INTO techo VALUES('abc', 'def', 'ghi')}                        \
   772    {INSERT INTO techo SELECT a||'.'||rowid, b, c FROM techo}              \
   773    {INSERT INTO techo SELECT a||'x'||rowid, b, c FROM techo}              \
   774    {INSERT INTO techo SELECT a||'y'||rowid, b, c FROM techo}              \
   775    {DELETE FROM techo WHERE (oid % 3) = 0}                                \
   776    {UPDATE techo set rowid = 100 WHERE rowid = 1}                         \
   777    {INSERT INTO techo(a, b) VALUES('hello', 'world')}                     \
   778    {DELETE FROM techo}                                                    \
   779  ] {
   780    execsql $stmt
   781    execsql $stmt db2
   782    check_echo_table vtab1-6.8.[incr tn]
   783  }
   784  
   785  db2 close
   786  
   787  
   788  
   789  #----------------------------------------------------------------------
   790  # Test cases vtab1-7 tests that the value returned by 
   791  # sqlite3_last_insert_rowid() is set correctly when rows are inserted
   792  # into virtual tables.
   793  do_test vtab1.7-1 {
   794    execsql {
   795      CREATE TABLE real_abc(a PRIMARY KEY, b, c);
   796      CREATE VIRTUAL TABLE echo_abc USING echo(real_abc);
   797    }
   798  } {}
   799  do_test vtab1.7-2 {
   800    execsql {
   801      INSERT INTO echo_abc VALUES(1, 2, 3);
   802      SELECT last_insert_rowid();
   803    }
   804  } {1}
   805  do_test vtab1.7-3 {
   806    execsql {
   807      INSERT INTO echo_abc(rowid) VALUES(31427);
   808      SELECT last_insert_rowid();
   809    }
   810  } {31427}
   811  do_test vtab1.7-4 {
   812    execsql {
   813      INSERT INTO echo_abc SELECT a||'.v2', b, c FROM echo_abc;
   814      SELECT last_insert_rowid();
   815    }
   816  } {31429}
   817  do_test vtab1.7-5 {
   818    execsql {
   819      SELECT rowid, a, b, c FROM echo_abc
   820    }
   821  } [list 1     1    2  3  \
   822          31427 {}   {} {} \
   823          31428 1.v2 2  3  \
   824          31429 {}  {} {}  \
   825  ]
   826  
   827  # Now test that DELETE and UPDATE operations do not modify the value.
   828  do_test vtab1.7-6 {
   829    execsql {
   830      UPDATE echo_abc SET c = 5 WHERE b = 2;
   831      SELECT last_insert_rowid();
   832    }
   833  } {31429}
   834  do_test vtab1.7-7 {
   835    execsql {
   836      UPDATE echo_abc SET rowid = 5 WHERE rowid = 1;
   837      SELECT last_insert_rowid();
   838    }
   839  } {31429}
   840  do_test vtab1.7-8 {
   841    execsql {
   842      DELETE FROM echo_abc WHERE b = 2;
   843      SELECT last_insert_rowid();
   844    }
   845  } {31429}
   846  do_test vtab1.7-9 {
   847    execsql {
   848      SELECT rowid, a, b, c FROM echo_abc
   849    }
   850  } [list 31427 {} {} {} \
   851          31429 {} {} {} \
   852  ]
   853  do_test vtab1.7-10 {
   854    execsql {
   855      DELETE FROM echo_abc WHERE b = 2;
   856      SELECT last_insert_rowid();
   857    }
   858  } {31429}
   859  do_test vtab1.7-11 {
   860    execsql {
   861      SELECT rowid, a, b, c FROM real_abc
   862    }
   863  } [list 31427 {} {} {} \
   864          31429 {} {} {} \
   865  ]
   866  do_test vtab1.7-12 {
   867    execsql {
   868      DELETE FROM echo_abc;
   869      SELECT last_insert_rowid();
   870    }
   871  } {31429}
   872  do_test vtab1.7-13 {
   873    execsql {
   874      SELECT rowid, a, b, c FROM real_abc
   875    }
   876  } {}
   877  
   878  # PRAGMA index_info and index_xinfo are no-ops on a virtual table
   879  do_test vtab1.7-14 {
   880    execsql {
   881      PRAGMA index_info('echo_abc');
   882      PRAGMA index_xinfo('echo_abc');
   883    }
   884  } {}
   885  
   886  ifcapable attach {
   887    do_test vtab1.8-1 {
   888      set echo_module ""
   889      execsql {
   890        ATTACH 'test2.db' AS aux;
   891        CREATE VIRTUAL TABLE aux.e2 USING echo(real_abc);
   892      }
   893      set echo_module
   894    } [list xCreate echo aux e2 real_abc   \
   895            xSync   echo(real_abc)         \
   896            xCommit echo(real_abc)         \
   897    ]
   898  }
   899  do_test vtab1.8-2 {
   900    catchsql {
   901      DROP TABLE aux.e2;
   902    }
   903    execsql {
   904      DROP TABLE treal;
   905      DROP TABLE techo;
   906      DROP TABLE echo_abc;
   907      DROP TABLE real_abc;
   908    }
   909  } {}
   910  
   911  do_test vtab1.9-1 {
   912    set echo_module ""
   913    execsql {
   914      CREATE TABLE r(a, b, c);
   915      CREATE VIRTUAL TABLE e USING echo(r, e_log);
   916      SELECT name FROM sqlite_master;
   917    }
   918  } {r e e_log}
   919  do_test vtab1.9-2 {
   920    execsql {
   921      DROP TABLE e;
   922      SELECT name FROM sqlite_master;
   923    }
   924  } {r}
   925  
   926  do_test vtab1.9-3 {
   927    set echo_module ""
   928    execsql {
   929      CREATE VIRTUAL TABLE e USING echo(r, e_log, virtual 1 2 3 varchar(32));
   930    }
   931    set echo_module
   932  } [list                                                        \
   933    xCreate echo main e r e_log {virtual 1 2 3 varchar(32)}      \
   934    xSync echo(r)                                                \
   935    xCommit echo(r)                                              \
   936  ]
   937  
   938  do_test vtab1.10-1 {
   939    execsql {
   940      CREATE TABLE del(d);
   941      CREATE VIRTUAL TABLE e2 USING echo(del);
   942    }
   943    db close
   944    sqlite3 db test.db
   945    register_echo_module [sqlite3_connection_pointer db]
   946    execsql {
   947      DROP TABLE del;
   948    }
   949    catchsql {
   950      SELECT * FROM e2;
   951    }
   952  } {1 {vtable constructor failed: e2}}
   953  do_test vtab1.10-2 {
   954    set rc [catch {
   955      set ptr [sqlite3_connection_pointer db]
   956      sqlite3_declare_vtab $ptr {CREATE TABLE abc(a, b, c)}
   957    } msg]
   958    list $rc $msg
   959  } {1 {bad parameter or other API misuse}}
   960  do_test vtab1.10-3 {
   961    set ::echo_module_begin_fail r
   962    catchsql {
   963      INSERT INTO e VALUES(1, 2, 3);
   964    }
   965  } {1 {SQL logic error}}
   966  do_test vtab1.10-4 {
   967    catch {execsql {
   968      EXPLAIN SELECT * FROM e WHERE rowid = 2;
   969      EXPLAIN QUERY PLAN SELECT * FROM e WHERE rowid = 2 ORDER BY rowid;
   970    }}
   971  } {0}
   972  
   973  do_test vtab1.10-5 {
   974    set echo_module ""
   975    execsql {
   976      SELECT * FROM e WHERE rowid||'' MATCH 'pattern';
   977    }
   978    set echo_module
   979  } [list \
   980    xBestIndex {SELECT rowid, a, b, c FROM 'r'} \
   981    xFilter {SELECT rowid, a, b, c FROM 'r'}    \
   982  ]
   983  proc match_func {args} {return ""}
   984  do_test vtab1.10-6 {
   985    set echo_module ""
   986    sqlite_delete_function db match
   987    db function match match_func
   988    execsql {
   989      SELECT * FROM e WHERE match('pattern', rowid, 'pattern2');
   990    }
   991    set echo_module
   992  } [list \
   993    xBestIndex {SELECT rowid, a, b, c FROM 'r'} \
   994    xFilter {SELECT rowid, a, b, c FROM 'r'}    \
   995  ]
   996  
   997  
   998  # Testing the xFindFunction interface
   999  #
  1000  catch {rename ::echo_glob_overload {}}
  1001  do_test vtab1.11-1 {
  1002    execsql {
  1003      INSERT INTO r(a,b,c) VALUES(1,'?',99);
  1004      INSERT INTO r(a,b,c) VALUES(2,3,99);
  1005      SELECT a GLOB b FROM e
  1006    }
  1007  } {1 0}
  1008  proc ::echo_glob_overload {a b} {
  1009   return [list $b $a]
  1010  }
  1011  do_test vtab1.11-2 {
  1012    execsql {
  1013      SELECT a like 'b' FROM e
  1014    }
  1015  } {0 0}
  1016  do_test vtab1.11-3 {
  1017    execsql {
  1018      SELECT a glob '2' FROM e
  1019    }
  1020  } {{1 2} {2 2}}
  1021  do_test vtab1.11-4 {
  1022    execsql {
  1023      SELECT  glob('2',a) FROM e
  1024    }
  1025  } {0 1}
  1026  do_test vtab1.11-5 {
  1027    execsql {
  1028      SELECT  glob(a,'2') FROM e
  1029    }
  1030  } {{2 1} {2 2}}
  1031   
  1032  #----------------------------------------------------------------------
  1033  # Test the outcome if a constraint is encountered half-way through
  1034  # a multi-row INSERT that is inside a transaction
  1035  #
  1036  do_test vtab1.12-1 {
  1037    execsql {
  1038      CREATE TABLE b(a, b, c);
  1039      CREATE TABLE c(a UNIQUE, b, c);
  1040      INSERT INTO b VALUES(1, 'A', 'B');
  1041      INSERT INTO b VALUES(2, 'C', 'D');
  1042      INSERT INTO b VALUES(3, 'E', 'F');
  1043      INSERT INTO c VALUES(3, 'G', 'H');
  1044      CREATE VIRTUAL TABLE echo_c USING echo(c);
  1045    }
  1046  } {}
  1047  
  1048  # First test outside of a transaction.
  1049  do_test vtab1.12-2 {
  1050    catchsql { INSERT INTO echo_c SELECT * FROM b; }
  1051  } {1 {echo-vtab-error: UNIQUE constraint failed: c.a}}
  1052  do_test vtab1.12-2.1 {
  1053    sqlite3_errmsg db
  1054  } {echo-vtab-error: UNIQUE constraint failed: c.a}
  1055  do_test vtab1.12-3 {
  1056    execsql { SELECT * FROM c }
  1057  } {3 G H}
  1058  
  1059  # Now the real test - wrapped in a transaction.
  1060  do_test vtab1.12-4 {
  1061    execsql  {BEGIN}
  1062    catchsql { INSERT INTO echo_c SELECT * FROM b; }
  1063  } {1 {echo-vtab-error: UNIQUE constraint failed: c.a}}
  1064  do_test vtab1.12-5 {
  1065    execsql { SELECT * FROM c }
  1066  } {3 G H}
  1067  do_test vtab1.12-6 {
  1068    execsql { COMMIT }
  1069    execsql { SELECT * FROM c }
  1070  } {3 G H}
  1071  
  1072  # At one point (ticket #2759), a WHERE clause of the form "<column> IS NULL"
  1073  # on a virtual table was causing an assert() to fail in the compiler.
  1074  #
  1075  # "IS NULL" clauses should not be passed through to the virtual table
  1076  # implementation. They are handled by SQLite after the vtab returns its
  1077  # data.
  1078  #
  1079  do_test vtab1.13-1 {
  1080    execsql { 
  1081      SELECT * FROM echo_c WHERE a IS NULL 
  1082    }
  1083  } {}
  1084  do_test vtab1.13-2 {
  1085    execsql { 
  1086      INSERT INTO c VALUES(NULL, 15, 16);
  1087      SELECT * FROM echo_c WHERE a IS NULL 
  1088    }
  1089  } {{} 15 16}
  1090  do_test vtab1.13-3 {
  1091    execsql { 
  1092      INSERT INTO c VALUES(15, NULL, 16);
  1093      SELECT * FROM echo_c WHERE b IS NULL 
  1094    }
  1095  } {15 {} 16}
  1096  do_test vtab1.13-4 {
  1097    unset -nocomplain null
  1098    execsql { 
  1099      SELECT * FROM echo_c WHERE b IS $null
  1100    }
  1101  } {15 {} 16}
  1102  do_test vtab1.13-5 {
  1103    execsql { 
  1104      SELECT * FROM echo_c WHERE b IS NULL AND a = 15;
  1105    }
  1106  } {15 {} 16}
  1107  do_test vtab1.13-6 {
  1108    execsql { 
  1109      SELECT * FROM echo_c WHERE NULL IS b AND a IS 15;
  1110    }
  1111  } {15 {} 16}
  1112  
  1113  
  1114  do_test vtab1-14.001 {
  1115    execsql {SELECT rowid, * FROM echo_c WHERE +rowid IN (1,2,3)}
  1116  } {1 3 G H 2 {} 15 16 3 15 {} 16}
  1117  do_test vtab1-14.002 {
  1118    execsql {SELECT rowid, * FROM echo_c WHERE rowid IN (1,2,3)}
  1119  } {1 3 G H 2 {} 15 16 3 15 {} 16}
  1120  do_test vtab1-14.003 {
  1121    execsql {SELECT rowid, * FROM echo_c WHERE +rowid IN (0,1,5,2,'a',3,NULL)}
  1122  } {1 3 G H 2 {} 15 16 3 15 {} 16}
  1123  do_test vtab1-14.004 {
  1124    execsql {SELECT rowid, * FROM echo_c WHERE rowid IN (0,1,5,'a',2,3,NULL)}
  1125  } {1 3 G H 2 {} 15 16 3 15 {} 16}
  1126  do_test vtab1-14.005 {
  1127    execsql {SELECT rowid, * FROM echo_c WHERE rowid NOT IN (0,1,5,'a',2,3)}
  1128  } {}
  1129  do_test vtab1-14.006 {
  1130    execsql {SELECT rowid, * FROM echo_c WHERE rowid NOT IN (0,5,'a',2,3)}
  1131  } {1 3 G H}
  1132  do_test vtab1-14.007 {
  1133    execsql {SELECT rowid, * FROM echo_c WHERE +rowid NOT IN (0,5,'a',2,3,NULL)}
  1134  } {}
  1135  do_test vtab1-14.008 {
  1136    execsql {SELECT rowid, * FROM echo_c WHERE rowid NOT IN (0,5,'a',2,3,NULL)}
  1137  } {}
  1138  do_test vtab1-14.011 {
  1139    execsql {SELECT * FROM echo_c WHERE +a IN (1,3,8,'x',NULL,15,24)}
  1140  } {3 G H 15 {} 16}
  1141  do_test vtab1-14.012 {
  1142    execsql {SELECT * FROM echo_c WHERE a IN (1,3,8,'x',NULL,15,24)}
  1143  } {3 G H 15 {} 16}
  1144  do_test vtab1-14.013 {
  1145    execsql {SELECT * FROM echo_c WHERE a NOT IN (1,8,'x',15,24)}
  1146  } {3 G H}
  1147  do_test vtab1-14.014 {
  1148    execsql {SELECT * FROM echo_c WHERE a NOT IN (1,8,'x',NULL,15,24)}
  1149  } {}
  1150  do_test vtab1-14.015 {
  1151    execsql {SELECT * FROM echo_c WHERE +a NOT IN (1,8,'x',NULL,15,24)}
  1152  } {}
  1153  
  1154  
  1155  
  1156  #do_test vtab1-14.1 {
  1157  #  execsql { DELETE FROM c }
  1158  #  set echo_module ""
  1159  #  execsql { SELECT * FROM echo_c WHERE rowid IN (1, 2, 3) }
  1160  #  set echo_module
  1161  #} {/.*xBestIndex {SELECT rowid, . FROM 'c' WHERE rowid = .} xFilter {SELECT rowid, . FROM 'c'} 1/}
  1162  
  1163  do_test vtab1-14.2 {
  1164    set echo_module ""
  1165    execsql { SELECT * FROM echo_c WHERE rowid = 1 }
  1166    set echo_module
  1167  } [list xBestIndex {SELECT rowid, a, b, c FROM 'c' WHERE rowid = ?} \
  1168          xFilter {SELECT rowid, a, b, c FROM 'c' WHERE rowid = ?} 1]
  1169  
  1170  do_test vtab1-14.3 {
  1171    set echo_module ""
  1172    execsql { SELECT * FROM echo_c WHERE a = 1 }
  1173    set echo_module
  1174  } [list xBestIndex {SELECT rowid, a, b, c FROM 'c' WHERE a = ?} \
  1175          xFilter {SELECT rowid, a, b, c FROM 'c' WHERE a = ?} 1]
  1176  
  1177  #do_test vtab1-14.4 {
  1178  #  set echo_module ""
  1179  #  execsql { SELECT * FROM echo_c WHERE a IN (1, 2) }
  1180  #  set echo_module
  1181  #} {/xBestIndex {SELECT rowid, . FROM 'c' WHERE a = .} xFilter {SELECT rowid, . FROM 'c' WHERE a = .} 1/}
  1182  
  1183  do_test vtab1-15.1 {
  1184    execsql {
  1185      CREATE TABLE t1(a, b, c);
  1186      CREATE VIRTUAL TABLE echo_t1 USING echo(t1);
  1187    }
  1188  } {}
  1189  do_test vtab1-15.2 {
  1190    execsql {
  1191      INSERT INTO echo_t1(rowid) VALUES(45);
  1192      SELECT rowid, * FROM echo_t1;
  1193    }
  1194  } {45 {} {} {}}
  1195  do_test vtab1-15.3 {
  1196    execsql {
  1197      INSERT INTO echo_t1(rowid) VALUES(NULL);
  1198      SELECT rowid, * FROM echo_t1;
  1199    }
  1200  } {45 {} {} {} 46 {} {} {}}
  1201  do_test vtab1-15.4 {
  1202    catchsql {
  1203      INSERT INTO echo_t1(rowid) VALUES('new rowid');
  1204    }
  1205  } {1 {datatype mismatch}}
  1206  
  1207  # The following tests - vtab1-16.* - are designed to test that setting 
  1208  # sqlite3_vtab.zErrMsg variable can be used by the vtab interface to 
  1209  # return an error message to the user.
  1210  # 
  1211  do_test vtab1-16.1 {
  1212    execsql {
  1213      CREATE TABLE t2(a PRIMARY KEY, b, c);
  1214      INSERT INTO t2 VALUES(1, 2, 3);
  1215      INSERT INTO t2 VALUES(4, 5, 6);
  1216      CREATE VIRTUAL TABLE echo_t2 USING echo(t2);
  1217    }
  1218  } {}
  1219  
  1220  set tn 2
  1221  foreach method [list \
  1222      xBestIndex       \
  1223      xOpen            \
  1224      xFilter          \
  1225      xNext            \
  1226      xColumn          \
  1227      xRowid           \
  1228  ] {
  1229    do_test vtab1-16.$tn {
  1230      set echo_module_fail($method,t2) "the $method method has failed"
  1231      catchsql { SELECT rowid, * FROM echo_t2 WHERE a >= 1 }
  1232    } "1 {echo-vtab-error: the $method method has failed}"
  1233    unset echo_module_fail($method,t2)
  1234    incr tn
  1235  }
  1236  
  1237  foreach method [list \
  1238    xUpdate            \
  1239    xBegin             \
  1240    xSync              \
  1241  ] {
  1242    do_test vtab1-16.$tn {
  1243      set echo_module_fail($method,t2) "the $method method has failed"
  1244      catchsql { INSERT INTO echo_t2 VALUES(7, 8, 9) }
  1245    } "1 {echo-vtab-error: the $method method has failed}"
  1246    unset echo_module_fail($method,t2)
  1247    incr tn
  1248  }
  1249  
  1250  ifcapable altertable {
  1251    do_test vtab1-16.$tn {
  1252      set echo_module_fail(xRename,t2) "the xRename method has failed"
  1253      catchsql { ALTER TABLE echo_t2 RENAME TO another_name }
  1254    } "1 {echo-vtab-error: the xRename method has failed}"
  1255    unset echo_module_fail(xRename,t2)
  1256    incr tn
  1257  }
  1258  
  1259  # The following test case exposes an instance in sqlite3_declare_vtab()
  1260  # an error message was set using a call similar to sqlite3_mprintf(zErr),
  1261  # where zErr is an arbitrary string. This is no good if the string contains
  1262  # characters that can be mistaken for printf() formatting directives.
  1263  #
  1264  do_test vtab1-17.1 {
  1265    sqlite3_db_config db DEFENSIVE 0
  1266    execsql { 
  1267      PRAGMA writable_schema = 1;
  1268      INSERT INTO sqlite_master VALUES(
  1269        'table', 't3', 't3', 0, 'INSERT INTO "%s%s" VALUES(1)'
  1270      );
  1271    }
  1272    catchsql { CREATE VIRTUAL TABLE t4 USING echo(t3); }
  1273  } {1 {vtable constructor failed: t4}}
  1274  
  1275  # This test verifies that ticket 48f29963 is fixed.
  1276  #
  1277  do_test vtab1-17.1 {
  1278    execsql { 
  1279      CREATE TABLE t5(a, b);
  1280      CREATE VIRTUAL TABLE e5 USING echo_v2(t5);
  1281      BEGIN;
  1282        INSERT INTO e5 VALUES(1, 2);
  1283        DROP TABLE e5;
  1284        SAVEPOINT one;
  1285        ROLLBACK TO one;
  1286      COMMIT;
  1287    }
  1288  } {}
  1289  
  1290  do_test vtab1-17.2 {
  1291    execsql { DELETE FROM sqlite_master WHERE sql LIKE 'insert%' }
  1292  } {}
  1293  
  1294  #-------------------------------------------------------------------------
  1295  # The following tests - vtab1-18.* - test that the optimization of LIKE
  1296  # constraints in where.c plays well with virtual tables.
  1297  #
  1298  #   18.1.*: Case-insensitive LIKE.
  1299  #   18.2.*: Case-sensitive LIKE.
  1300  #
  1301  unset -nocomplain echo_module_begin_fail
  1302  
  1303  do_execsql_test 18.1.0 {
  1304    CREATE TABLE t6(a, b TEXT);
  1305    CREATE INDEX i6 ON t6(b, a);
  1306    INSERT INTO t6 VALUES(1, 'Peter');
  1307    INSERT INTO t6 VALUES(2, 'Andrew');
  1308    INSERT INTO t6 VALUES(3, '8James');
  1309    INSERT INTO t6 VALUES(4, '8John');
  1310    INSERT INTO t6 VALUES(5, 'Phillip');
  1311    INSERT INTO t6 VALUES(6, 'Bartholomew');
  1312    CREATE VIRTUAL TABLE e6 USING echo(t6);
  1313  }
  1314  
  1315  ifcapable !icu {
  1316    foreach {tn sql res filter} {
  1317      1.1 "SELECT a FROM e6 WHERE b>'8James'" {4 2 6 1 5}
  1318        {xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} 8James}
  1319    
  1320      1.2 "SELECT a FROM e6 WHERE b>='8' AND b<'9'" {3 4}
  1321        {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9}
  1322    
  1323      1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4}
  1324        {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8J%}
  1325    
  1326      1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4}
  1327        {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8j%}
  1328    
  1329      1.5 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4}
  1330        {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%}
  1331    } {
  1332      set echo_module {}
  1333      do_execsql_test 18.$tn.1 $sql $res
  1334      do_test         18.$tn.2 { lrange $::echo_module 2 end } $filter
  1335    }
  1336  }
  1337  
  1338  do_execsql_test 18.2.0 {  PRAGMA case_sensitive_like = ON }
  1339  foreach {tn sql res filter} {
  1340    2.1 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4}
  1341      {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%}
  1342  
  1343    2.2 "SELECT a FROM e6 WHERE b LIKE '8j%'" {}
  1344      {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8j 8k 8j%}
  1345  
  1346    2.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4}
  1347      {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8K 8J%}
  1348  } {
  1349    set echo_module {}
  1350    do_execsql_test 18.$tn.1 $sql $res
  1351    do_test         18.$tn.2 { lrange $::echo_module 2 end } $filter
  1352  }
  1353  do_execsql_test 18.2.x {  PRAGMA case_sensitive_like = OFF }
  1354  
  1355  #-------------------------------------------------------------------------
  1356  # Test that it is ok to override and existing module.
  1357  #
  1358  do_test 19.1 {
  1359    sqlite3 db2 test.db
  1360    register_echo_module [sqlite3_connection_pointer db2]
  1361  } SQLITE_OK
  1362  do_test 19.2 {
  1363    register_echo_module [sqlite3_connection_pointer db2]
  1364  } SQLITE_OK
  1365  do_test 19.3 {
  1366    db2 close
  1367  } {}
  1368  
  1369  #-------------------------------------------------------------------------
  1370  # Test that the bug fixed by [b0c1ba655d69] really is fixed.
  1371  #
  1372  do_execsql_test 20.1 {
  1373    CREATE TABLE t7 (a, b);
  1374    CREATE TABLE t8 (c, d);
  1375    CREATE INDEX i2 ON t7(a);
  1376    CREATE INDEX i3 ON t7(b);
  1377    CREATE INDEX i4 ON t8(c);
  1378    CREATE INDEX i5 ON t8(d);
  1379  
  1380    CREATE VIRTUAL TABLE t7v USING echo(t7);
  1381    CREATE VIRTUAL TABLE t8v USING echo(t8);
  1382  }
  1383  
  1384  do_test 20.2 {
  1385    for {set i 0} {$i < 1000} {incr i} {
  1386      db eval {INSERT INTO t7 VALUES($i, $i)}
  1387      db eval {INSERT INTO t8 VALUES($i, $i)}
  1388    }
  1389  } {}
  1390  
  1391  do_execsql_test 20.3 {
  1392    SELECT a, b FROM (
  1393        SELECT a, b FROM t7 WHERE a=11 OR b=12
  1394        UNION ALL
  1395        SELECT c, d FROM t8 WHERE c=5 OR d=6
  1396    )
  1397    ORDER BY 1, 2;
  1398  } {5 5 6 6 11 11 12 12}
  1399  
  1400  do_execsql_test 20.4 {
  1401    SELECT a, b FROM (
  1402        SELECT a, b FROM t7v WHERE a=11 OR b=12
  1403        UNION ALL
  1404        SELECT c, d FROM t8v WHERE c=5 OR d=6
  1405    )
  1406    ORDER BY 1, 2;
  1407  } {5 5 6 6 11 11 12 12}
  1408  
  1409  #-------------------------------------------------------------------------
  1410  #
  1411  do_execsql_test 21.1 {
  1412    CREATE TABLE t9(a,b,c);
  1413    CREATE VIRTUAL TABLE t9v USING echo(t9);
  1414  
  1415    INSERT INTO t9 VALUES(1,2,3);
  1416    INSERT INTO t9 VALUES(3,2,1);
  1417    INSERT INTO t9 VALUES(2,2,2);
  1418  }
  1419  
  1420  do_execsql_test 21.2 {
  1421    SELECT * FROM t9v WHERE a<b;
  1422  } {1 2 3}
  1423  
  1424  do_execsql_test 21.3 {
  1425    SELECT * FROM t9v WHERE a=b;
  1426  } {2 2 2}
  1427  
  1428  #-------------------------------------------------------------------------
  1429  # At one point executing a CREATE VIRTUAL TABLE statement that specified 
  1430  # a database name but no virtual table arguments was causing an internal
  1431  # buffer overread. Valgrind would report errors while running the following 
  1432  # tests. Specifically:
  1433  #
  1434  #   CREATE VIRTUAL TABLE t1 USING fts4;          -- Ok - no db name.
  1435  #   CREATE VIRTUAL TABLE main.t1 USING fts4(x);  -- Ok - has vtab arguments.
  1436  #   CREATE VIRTUAL TABLE main.t1 USING fts4;     -- Had the problem. 
  1437  #
  1438  ifcapable fts3 {
  1439    forcedelete test.db2
  1440    set nm [string repeat abcdefghij 100]
  1441    do_execsql_test 22.1 {
  1442      ATTACH 'test.db2' AS $nm
  1443    }
  1444    
  1445    execsql "SELECT * FROM sqlite_master"
  1446    do_execsql_test 22.2 "CREATE VIRTUAL TABLE ${nm}.t1 USING fts4"
  1447    
  1448    do_test 22.3.1 {
  1449      set sql "CREATE VIRTUAL TABLE ${nm}.t2 USING fts4"
  1450      set stmt [sqlite3_prepare_v2 db $sql -1 dummy]
  1451      sqlite3_step $stmt
  1452    } {SQLITE_DONE}
  1453    
  1454    do_test 22.3.2 {
  1455      sqlite3_finalize $stmt
  1456    } {SQLITE_OK}
  1457    
  1458    do_test 22.4.1 {
  1459      set sql "CREATE VIRTUAL TABLE ${nm}.t3 USING fts4"
  1460      set n [string length $sql]
  1461      set stmt [sqlite3_prepare db "${sql}xyz" $n dummy]
  1462      sqlite3_step $stmt
  1463    } {SQLITE_DONE}
  1464    
  1465    do_test 22.4.2 {
  1466      sqlite3_finalize $stmt
  1467    } {SQLITE_OK}
  1468  }
  1469  
  1470  
  1471  #-------------------------------------------------------------------------
  1472  # The following tests verify that a DROP TABLE command on a virtual
  1473  # table does not cause other operations to crash.
  1474  #
  1475  #   23.1: Dropping a vtab while a SELECT is running on it.
  1476  #
  1477  #   23.2: Dropping a vtab while a SELECT that will, but has not yet,
  1478  #         open a cursor on the vtab, is running. In this case the
  1479  #         DROP TABLE succeeds and the SELECT hits an error.
  1480  #   
  1481  #   23.3: Dropping a vtab from within a user-defined-function callback
  1482  #         in the middle of an "INSERT INTO vtab SELECT ..." statement.
  1483  #
  1484  reset_db
  1485  load_static_extension db wholenumber
  1486  load_static_extension db eval
  1487  register_echo_module db
  1488  
  1489  do_test 23.1 {
  1490    execsql { CREATE VIRTUAL TABLE t1 USING wholenumber }
  1491    set res ""
  1492    db eval { SELECT value FROM t1 WHERE value<10 } {
  1493      if {$value == 5} {
  1494        set res [catchsql { DROP TABLE t1 }]
  1495      }
  1496    }
  1497    set res
  1498  } {1 {database table is locked}}
  1499  
  1500  do_test 23.2 {
  1501    execsql { 
  1502      CREATE TABLE t2(value);
  1503      INSERT INTO t2 VALUES(1), (2), (3);
  1504    }
  1505  
  1506    set res2 [list [catch {
  1507      db eval {
  1508        SELECT value FROM t2 UNION ALL 
  1509        SELECT value FROM t1 WHERE value<10
  1510      } {
  1511        if {$value == 2} { set res1 [catchsql { DROP TABLE t1 }] }
  1512      }
  1513    } msg] $msg]
  1514    list $res1 $res2
  1515  } {{0 {}} {1 {database table is locked}}}
  1516  
  1517  do_test 23.3.1 {
  1518    execsql { CREATE VIRTUAL TABLE t1e USING echo(t2) }
  1519    execsql { INSERT INTO t1e SELECT 4 }
  1520    catchsql { INSERT INTO t1e SELECT eval('DROP TABLE t1e') }
  1521  } {1 {database table is locked}}
  1522  do_execsql_test 23.3.2 { SELECT * FROM t1e } {1 2 3 4}
  1523  
  1524  #-------------------------------------------------------------------------
  1525  # At one point SQL like this:
  1526  #
  1527  #   SAVEPOINT xyz;       -- Opens SQL transaction
  1528  #     INSERT INTO vtab   -- Write to virtual table
  1529  #     ROLLBACK TO xyz;
  1530  #   RELEASE xyz;
  1531  #
  1532  # was not invoking the xRollbackTo() callback for the ROLLBACK TO 
  1533  # operation. Which meant that virtual tables like FTS3 would incorrectly 
  1534  # commit the results of the INSERT as part of the "RELEASE xyz" command.
  1535  #
  1536  # The following tests check that this has been fixed.
  1537  #
  1538  ifcapable fts3 {
  1539    do_execsql_test 24.0 {
  1540      CREATE VIRTUAL TABLE t4 USING fts3();
  1541      SAVEPOINT a;
  1542      INSERT INTO t4 VALUES('a b c');
  1543      ROLLBACK TO a;
  1544      RELEASE a;
  1545      SELECT * FROM t4;
  1546    } {}
  1547  
  1548    do_execsql_test 24.1 { SELECT * FROM t4 WHERE t4 MATCH 'b' } {}
  1549    do_execsql_test 24.2 { INSERT INTO t4(t4) VALUES('integrity-check') } {}
  1550  
  1551    do_execsql_test 24.3 {
  1552      SAVEPOINT a;
  1553      CREATE VIRTUAL TABLE t5 USING fts3();
  1554      SAVEPOINT b;
  1555      ROLLBACK TO a;
  1556      SAVEPOINT c;
  1557      RELEASE a;
  1558    }
  1559  }
  1560  
  1561  # 2021-07-04 https://sqlite.org/forum/forumpost/16ca0e9f32
  1562  # Yu Liang crash involving UPDATE on a virtual table with
  1563  # a duplicate column in a vector changeset and invoking the
  1564  # query flattener for UNION ALL.
  1565  #
  1566  reset_db
  1567  register_echo_module db
  1568  do_catchsql_test 25.0 {
  1569    CREATE TABLE t0(a);
  1570    CREATE VIRTUAL TABLE t1 USING echo(t0);
  1571    WITH t3(a) AS (SELECT * FROM t1 UNION ALL SELECT * FROM t1)
  1572    UPDATE t1 SET (a,a) = (SELECT 1, 0) FROM t3;
  1573  } {0 {}}
  1574  
  1575  #--------------------------------------------------------------------------
  1576  #
  1577  reset_db
  1578  load_static_extension db wholenumber
  1579  do_execsql_test 26.1 {
  1580    CREATE VIRTUAL TABLE t1 USING wholenumber;
  1581    CREATE TABLE tx(a, b, c);
  1582  }
  1583  do_test 26.2 {
  1584    sqlite3 db2 test.db
  1585    db2 eval { CREATE TABLE ty(x, y) }
  1586    db2 close
  1587  } {}
  1588  do_execsql_test 26.3 {
  1589    SELECT value FROM t1 WHERE value<5
  1590  } {1 2 3 4}
  1591  
  1592  
  1593  finish_test