Annotation of embedaddon/sqlite3/test/vtab1.test, revision 1.1.1.1

1.1       misho       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: 
                     19: ifcapable !vtab||!schema_pragmas {
                     20:   finish_test
                     21:   return
                     22: }
                     23: 
                     24: #----------------------------------------------------------------------
                     25: # Organization of tests in this file:
                     26: #
                     27: # vtab1-1.*: Error conditions and other issues surrounding creation/connection
                     28: #            of a virtual module.
                     29: # vtab1-2.*: Test sqlite3_declare_vtab() and the xConnect/xDisconnect methods.
                     30: # vtab1-3.*: Table scans and WHERE clauses.
                     31: # vtab1-4.*: Table scans and ORDER BY clauses.
                     32: # vtab1-5.*: Test queries that include joins. This brings the
                     33: #            sqlite3_index_info.estimatedCost variable into play.
                     34: # vtab1-6.*: Test UPDATE/INSERT/DELETE on vtables.
                     35: # vtab1-7.*: Test sqlite3_last_insert_rowid().
                     36: #
                     37: # This file uses the "echo" module (see src/test8.c). Refer to comments
                     38: # in that file for the special behaviour of the Tcl $echo_module variable.
                     39: #
                     40: # TODO: 
                     41: #   * How to test the sqlite3_index_constraint_usage.omit field?
                     42: #   * vtab1-5.*
                     43: #
                     44: # vtab1-14.*: Test 'IN' constraints - i.e. "SELECT * FROM t1 WHERE id IN(...)"
                     45: #
                     46: 
                     47: 
                     48: #----------------------------------------------------------------------
                     49: # Test cases vtab1.1.*
                     50: #
                     51: 
                     52: # We cannot create a virtual table if the module has not been registered.
                     53: #
                     54: do_test vtab1-1.1 {
                     55:   explain {
                     56:     CREATE VIRTUAL TABLE t1 USING echo;
                     57:   }
                     58:   catchsql {
                     59:     CREATE VIRTUAL TABLE t1 USING echo;
                     60:   }
                     61: } {1 {no such module: echo}}
                     62: do_test vtab1-1.2 {
                     63:   execsql {
                     64:     SELECT name FROM sqlite_master ORDER BY 1
                     65:   }
                     66: } {}
                     67: 
                     68: # Register the module
                     69: register_echo_module [sqlite3_connection_pointer db]
                     70: 
                     71: # Once a module has been registered, virtual tables using that module
                     72: # may be created. However if a module xCreate() fails to call
                     73: # sqlite3_declare_vtab() an error will be raised and the table not created.
                     74: #
                     75: # The "echo" module does not invoke sqlite3_declare_vtab() if it is
                     76: # passed zero arguments.
                     77: #
                     78: do_test vtab1-1.3 {
                     79:   catchsql {
                     80:     CREATE VIRTUAL TABLE t1 USING echo;
                     81:   }
                     82: } {1 {vtable constructor did not declare schema: t1}}
                     83: do_test vtab1-1.4 {
                     84:   execsql {
                     85:     SELECT name FROM sqlite_master ORDER BY 1
                     86:   }
                     87: } {}
                     88: 
                     89: # The "echo" module xCreate method returns an error and does not create
                     90: # the virtual table if it is passed an argument that does not correspond
                     91: # to an existing real table in the same database.
                     92: #
                     93: do_test vtab1-1.5 {
                     94:   catchsql {
                     95:     CREATE VIRTUAL TABLE t1 USING echo(no_such_table);
                     96:   }
                     97: } {1 {vtable constructor failed: t1}}
                     98: do_test vtab1-1.6 {
                     99:   execsql {
                    100:     SELECT name FROM sqlite_master ORDER BY 1
                    101:   }
                    102: } {}
                    103: 
                    104: # Ticket #2156.  Using the sqlite3_prepare_v2() API, make sure that
                    105: # a CREATE VIRTUAL TABLE statement can be used multiple times.
                    106: #
                    107: do_test vtab1-1.2152.1 {
                    108:   set DB [sqlite3_connection_pointer db]
                    109:   set sql {CREATE VIRTUAL TABLE t2152a USING echo(t2152b)}
                    110:   set STMT [sqlite3_prepare_v2 $DB $sql -1 TAIL]
                    111:   sqlite3_step $STMT
                    112: } SQLITE_ERROR
                    113: do_test vtab-1.2152.2 {
                    114:   sqlite3_reset $STMT
                    115:   sqlite3_step $STMT
                    116: } SQLITE_ERROR
                    117: do_test vtab-1.2152.3 {
                    118:   sqlite3_reset $STMT
                    119:   db eval {CREATE TABLE t2152b(x,y)}
                    120:   sqlite3_step $STMT
                    121: } SQLITE_DONE
                    122: do_test vtab-1.2152.4 {
                    123:   sqlite3_finalize $STMT
                    124:   db eval {DROP TABLE t2152a; DROP TABLE t2152b}
                    125: } {}
                    126: 
                    127: # Test to make sure nothing goes wrong and no memory is leaked if we 
                    128: # select an illegal table-name (i.e a reserved name or the name of a
                    129: # table that already exists).
                    130: #
                    131: do_test vtab1-1.7 {
                    132:   catchsql {
                    133:     CREATE VIRTUAL TABLE sqlite_master USING echo;
                    134:   }
                    135: } {1 {object name reserved for internal use: sqlite_master}}
                    136: do_test vtab1-1.8 {
                    137:   catchsql {
                    138:     CREATE TABLE treal(a, b, c);
                    139:     CREATE VIRTUAL TABLE treal USING echo(treal);
                    140:   }
                    141: } {1 {table treal already exists}}
                    142: do_test vtab1-1.9 {
                    143:   execsql {
                    144:     DROP TABLE treal;
                    145:     SELECT name FROM sqlite_master ORDER BY 1
                    146:   }
                    147: } {}
                    148: 
                    149: do_test vtab1-1.10 {
                    150:   execsql {
                    151:     CREATE TABLE treal(a, b, c);
                    152:     CREATE VIRTUAL TABLE techo USING echo(treal);
                    153:   }
                    154:   db close
                    155:   sqlite3 db test.db
                    156:   catchsql {
                    157:     SELECT * FROM techo;
                    158:   }
                    159: } {1 {no such module: echo}}
                    160: do_test vtab1-1.11 {
                    161:   catchsql {
                    162:     INSERT INTO techo VALUES(1, 2, 3);
                    163:   }
                    164: } {1 {no such module: echo}}
                    165: do_test vtab1-1.12 {
                    166:   catchsql {
                    167:     UPDATE techo SET a = 10;
                    168:   }
                    169: } {1 {no such module: echo}}
                    170: do_test vtab1-1.13 {
                    171:   catchsql {
                    172:     DELETE FROM techo;
                    173:   }
                    174: } {1 {no such module: echo}}
                    175: do_test vtab1-1.14 {
                    176:   catchsql {
                    177:     PRAGMA table_info(techo)
                    178:   }
                    179: } {1 {no such module: echo}}
                    180: do_test vtab1-1.15 {
                    181:   catchsql {
                    182:     DROP TABLE techo;
                    183:   }
                    184: } {1 {no such module: echo}}
                    185: 
                    186: register_echo_module [sqlite3_connection_pointer db]
                    187: register_echo_module [sqlite3_connection_pointer db]
                    188: 
                    189: # Test an error message returned from a v-table constructor.
                    190: #
                    191: do_test vtab1-1.16 {
                    192:   execsql {
                    193:     DROP TABLE techo;
                    194:     CREATE TABLE logmsg(log);
                    195:   }
                    196:   catchsql {
                    197:     CREATE VIRTUAL TABLE techo USING echo(treal, logmsg);
                    198:   }
                    199: } {1 {table 'logmsg' already exists}}
                    200: 
                    201: do_test vtab1-1.17 {
                    202:   execsql {
                    203:     DROP TABLE treal;
                    204:     DROP TABLE logmsg;
                    205:     SELECT sql FROM sqlite_master;
                    206:   }
                    207: } {}
                    208: 
                    209: #----------------------------------------------------------------------
                    210: # Test cases vtab1.2.*
                    211: #
                    212: # At this point, the database is completely empty. The echo module
                    213: # has already been registered.
                    214: 
                    215: # If a single argument is passed to the echo module during table
                    216: # creation, it is assumed to be the name of a table in the same
                    217: # database. The echo module attempts to set the schema of the
                    218: # new virtual table to be the same as the existing database table.
                    219: #
                    220: do_test vtab1-2.1 {
                    221:   execsql {
                    222:     CREATE TABLE template(a, b, c);
                    223:   }
                    224:   execsql { PRAGMA table_info(template); }
                    225: } [list         \
                    226:   0 a {} 0 {} 0 \
                    227:   1 b {} 0 {} 0 \
                    228:   2 c {} 0 {} 0 \
                    229: ]
                    230: do_test vtab1-2.2 {
                    231:   execsql {
                    232:     CREATE VIRTUAL TABLE t1 USING echo(template);
                    233:   }
                    234:   execsql { PRAGMA table_info(t1); }
                    235: } [list         \
                    236:   0 a {} 0 {} 0 \
                    237:   1 b {} 0 {} 0 \
                    238:   2 c {} 0 {} 0 \
                    239: ]
                    240: 
                    241: # Test that the database can be unloaded. This should invoke the xDisconnect()
                    242: # callback for the successfully create virtual table (t1).
                    243: #
                    244: do_test vtab1-2.3 {
                    245:   set echo_module [list]
                    246:   db close
                    247:   set echo_module
                    248: } [list xDisconnect]
                    249: 
                    250: # Re-open the database. This should not cause any virtual methods to 
                    251: # be called. The invocation of xConnect() is delayed until the virtual
                    252: # table schema is first required by the compiler.
                    253: #
                    254: do_test vtab1-2.4 {
                    255:   set echo_module [list]
                    256:   sqlite3 db test.db
                    257:   db cache size 0
                    258:   set echo_module
                    259: } {}
                    260: 
                    261: # Try to query the virtual table schema. This should fail, as the
                    262: # echo module has not been registered with this database connection.
                    263: #
                    264: do_test vtab1.2.6 {
                    265:   catchsql { PRAGMA table_info(t1); }
                    266: } {1 {no such module: echo}}
                    267: 
                    268: # Register the module
                    269: register_echo_module [sqlite3_connection_pointer db]
                    270: 
                    271: # Try to query the virtual table schema again. This time it should
                    272: # invoke the xConnect method and succeed.
                    273: #
                    274: do_test vtab1.2.7 {
                    275:   execsql { PRAGMA table_info(t1); }
                    276: } [list         \
                    277:   0 a {} 0 {} 0 \
                    278:   1 b {} 0 {} 0 \
                    279:   2 c {} 0 {} 0 \
                    280: ]
                    281: do_test vtab1.2.8 {
                    282:   set echo_module
                    283: } {xConnect echo main t1 template}
                    284: 
                    285: # Drop table t1. This should cause the xDestroy (but not xDisconnect) method 
                    286: # to be invoked.
                    287: do_test vtab1-2.5 {
                    288:   set echo_module ""
                    289:   execsql {
                    290:     DROP TABLE t1;
                    291:   }
                    292:   set echo_module
                    293: } {xDestroy}
                    294: 
                    295: do_test vtab1-2.6 {
                    296:   execsql { 
                    297:     PRAGMA table_info(t1); 
                    298:   }
                    299: } {}
                    300: do_test vtab1-2.7 {
                    301:   execsql {
                    302:     SELECT sql FROM sqlite_master;
                    303:   }
                    304: } [list {CREATE TABLE template(a, b, c)}]
                    305: # Clean up other test artifacts:
                    306: do_test vtab1-2.8 {
                    307:   execsql { 
                    308:     DROP TABLE template;
                    309:     SELECT sql FROM sqlite_master;
                    310:   }
                    311: } [list]
                    312: 
                    313: #----------------------------------------------------------------------
                    314: # Test case vtab1-3 test table scans and the echo module's 
                    315: # xBestIndex/xFilter handling of WHERE conditions.
                    316: 
                    317: do_test vtab1-3.1 {
                    318:   set echo_module ""
                    319:   execsql {
                    320:     CREATE TABLE treal(a INTEGER, b INTEGER, c); 
                    321:     CREATE INDEX treal_idx ON treal(b);
                    322:     CREATE VIRTUAL TABLE t1 USING echo(treal);
                    323:   }
                    324:   set echo_module
                    325: } [list xCreate echo main t1 treal   \
                    326:         xSync   echo(treal)  \
                    327:         xCommit echo(treal)  \
                    328: ]
                    329: 
                    330: # Test that a SELECT on t1 doesn't crash. No rows are returned
                    331: # because the underlying real table is currently empty.
                    332: #
                    333: do_test vtab1-3.2 {
                    334:   execsql {
                    335:     SELECT a, b, c FROM t1;
                    336:   }
                    337: } {}
                    338: 
                    339: # Put some data into the table treal. Then try a few simple SELECT 
                    340: # statements on t1.
                    341: #
                    342: do_test vtab1-3.3 {
                    343:   execsql {
                    344:     INSERT INTO treal VALUES(1, 2, 3);
                    345:     INSERT INTO treal VALUES(4, 5, 6);
                    346:     SELECT * FROM t1;
                    347:   }
                    348: } {1 2 3 4 5 6}
                    349: do_test vtab1-3.4 {
                    350:   execsql {
                    351:     SELECT a FROM t1;
                    352:   }
                    353: } {1 4}
                    354: do_test vtab1-3.5 {
                    355:   execsql {
                    356:     SELECT rowid FROM t1;
                    357:   }
                    358: } {1 2}
                    359: do_test vtab1-3.6 {
                    360:   set echo_module ""
                    361:   execsql {
                    362:     SELECT * FROM t1;
                    363:   }
                    364: } {1 2 3 4 5 6}
                    365: do_test vtab1-3.7 {
                    366:   execsql {
                    367:     SELECT rowid, * FROM t1;
                    368:   }
                    369: } {1 1 2 3 2 4 5 6}
                    370: do_test vtab1-3.8 {
                    371:   execsql {
                    372:     SELECT a AS d, b AS e, c AS f FROM t1;
                    373:   }
                    374: } {1 2 3 4 5 6}
                    375: 
                    376: # Execute some SELECT statements with WHERE clauses on the t1 table.
                    377: # Then check the echo_module variable (written to by the module methods
                    378: # in test8.c) to make sure the xBestIndex() and xFilter() methods were
                    379: # called correctly.
                    380: #
                    381: do_test vtab1-3.8 {
                    382:   set echo_module ""
                    383:   execsql {
                    384:     SELECT * FROM t1;
                    385:   }
                    386:   set echo_module
                    387: } [list xBestIndex {SELECT rowid, * FROM 'treal'} \
                    388:         xFilter    {SELECT rowid, * FROM 'treal'} ]
                    389: do_test vtab1-3.9 {
                    390:   set echo_module ""
                    391:   execsql {
                    392:     SELECT * FROM t1 WHERE b = 5;
                    393:   }
                    394: } {4 5 6}
                    395: do_test vtab1-3.10 {
                    396:   set echo_module
                    397: } [list xBestIndex {SELECT rowid, * FROM 'treal' WHERE b = ?}   \
                    398:         xFilter    {SELECT rowid, * FROM 'treal' WHERE b = ?} 5 ]
                    399: do_test vtab1-3.10 {
                    400:   set echo_module ""
                    401:   execsql {
                    402:     SELECT * FROM t1 WHERE b >= 5 AND b <= 10;
                    403:   }
                    404: } {4 5 6}
                    405: do_test vtab1-3.11 {
                    406:   set echo_module
                    407: } [list xBestIndex {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?}      \
                    408:         xFilter    {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} 5 10 ]
                    409: do_test vtab1-3.12 {
                    410:   set echo_module ""
                    411:   execsql {
                    412:     SELECT * FROM t1 WHERE b BETWEEN 2 AND 10;
                    413:   }
                    414: } {1 2 3 4 5 6}
                    415: do_test vtab1-3.13 {
                    416:   set echo_module
                    417: } [list xBestIndex {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?}      \
                    418:         xFilter    {SELECT rowid, * FROM 'treal' WHERE b >= ? AND b <= ?} 2 10 ]
                    419: 
                    420: # Add a function for the MATCH operator. Everything always matches!
                    421: #proc test_match {lhs rhs} {
                    422: #  lappend ::echo_module MATCH $lhs $rhs
                    423: #  return 1
                    424: #}
                    425: #db function match test_match
                    426: 
                    427: set echo_module ""
                    428: do_test vtab1-3.12 {
                    429:   set echo_module ""
                    430:   catchsql {
                    431:     SELECT * FROM t1 WHERE a MATCH 'string';
                    432:   }
                    433: } {1 {unable to use function MATCH in the requested context}}
                    434: do_test vtab1-3.13 {
                    435:   set echo_module
                    436: } [list xBestIndex {SELECT rowid, * FROM 'treal'} \
                    437:         xFilter    {SELECT rowid, * FROM 'treal'}]
                    438: ifcapable subquery {
                    439: # The echo module uses a subquery internally to implement the MATCH operator.
                    440: do_test vtab1-3.14 {
                    441:   set echo_module ""
                    442:   execsql {
                    443:     SELECT * FROM t1 WHERE b MATCH 'string';
                    444:   }
                    445: } {}
                    446: do_test vtab1-3.15 {
                    447:   set echo_module
                    448: } [list xBestIndex \
                    449:         {SELECT rowid, * FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')}  \
                    450:         xFilter \
                    451:         {SELECT rowid, * FROM 'treal' WHERE b LIKE (SELECT '%'||?||'%')} \
                    452:         string ]
                    453: }; #ifcapable subquery
                    454: 
                    455: #----------------------------------------------------------------------
                    456: # Test case vtab1-3 test table scans and the echo module's 
                    457: # xBestIndex/xFilter handling of ORDER BY clauses.
                    458: 
                    459: # This procedure executes the SQL.  Then it checks to see if the OP_Sort
                    460: # opcode was executed.  If an OP_Sort did occur, then "sort" is appended
                    461: # to the result.  If no OP_Sort happened, then "nosort" is appended.
                    462: #
                    463: # This procedure is used to check to make sure sorting is or is not
                    464: # occurring as expected.
                    465: #
                    466: proc cksort {sql} {
                    467:   set ::sqlite_sort_count 0
                    468:   set data [execsql $sql]
                    469:   if {$::sqlite_sort_count} {set x sort} {set x nosort}
                    470:   lappend data $x
                    471:   return $data
                    472: }
                    473: 
                    474: do_test vtab1-4.1 {
                    475:   set echo_module ""
                    476:   cksort {
                    477:     SELECT b FROM t1 ORDER BY b;
                    478:   }
                    479: } {2 5 nosort}
                    480: do_test vtab1-4.2 {
                    481:   set echo_module
                    482: } [list xBestIndex {SELECT rowid, * FROM 'treal' ORDER BY b ASC} \
                    483:         xFilter    {SELECT rowid, * FROM 'treal' ORDER BY b ASC} ]
                    484: do_test vtab1-4.3 {
                    485:   set echo_module ""
                    486:   cksort {
                    487:     SELECT b FROM t1 ORDER BY b DESC;
                    488:   }
                    489: } {5 2 nosort}
                    490: do_test vtab1-4.4 {
                    491:   set echo_module
                    492: } [list xBestIndex {SELECT rowid, * FROM 'treal' ORDER BY b DESC} \
                    493:         xFilter    {SELECT rowid, * FROM 'treal' ORDER BY b DESC} ]
                    494: do_test vtab1-4.3 {
                    495:   set echo_module ""
                    496:   cksort {
                    497:     SELECT b FROM t1 ORDER BY b||'';
                    498:   }
                    499: } {2 5 sort}
                    500: do_test vtab1-4.4 {
                    501:   set echo_module
                    502: } [list xBestIndex {SELECT rowid, * FROM 'treal'} \
                    503:         xFilter    {SELECT rowid, * FROM 'treal'} ]
                    504: 
                    505: execsql {
                    506:   DROP TABLE t1;
                    507:   DROP TABLE treal;
                    508: }
                    509: 
                    510: #----------------------------------------------------------------------
                    511: # Test cases vtab1-5 test SELECT queries that include joins on virtual 
                    512: # tables.
                    513: 
                    514: proc filter {log} {
                    515:   set out [list]
                    516:   for {set ii 0} {$ii < [llength $log]} {incr ii} {
                    517:     if {[lindex $log $ii] eq "xFilter"} {
                    518:       lappend out xFilter
                    519:       lappend out [lindex $log [expr $ii+1]]
                    520:     }
                    521:   }
                    522:   return $out
                    523: }
                    524: 
                    525: do_test vtab1-5-1 {
                    526:   execsql { 
                    527:     CREATE TABLE t1(a, b, c);
                    528:     CREATE TABLE t2(d, e, f);
                    529:     INSERT INTO t1 VALUES(1, 'red', 'green');
                    530:     INSERT INTO t1 VALUES(2, 'blue', 'black');
                    531:     INSERT INTO t2 VALUES(1, 'spades', 'clubs');
                    532:     INSERT INTO t2 VALUES(2, 'hearts', 'diamonds');
                    533:     CREATE VIRTUAL TABLE et1 USING echo(t1);
                    534:     CREATE VIRTUAL TABLE et2 USING echo(t2);
                    535:   }
                    536: } {}
                    537: 
                    538: do_test vtab1-5-2 {
                    539:   set echo_module ""
                    540:   execsql {
                    541:     SELECT * FROM et1, et2;
                    542:   }
                    543: } [list \
                    544:   1 red green 1 spades clubs     \
                    545:   1 red green 2 hearts diamonds  \
                    546:   2 blue black 1 spades clubs    \
                    547:   2 blue black 2 hearts diamonds \
                    548: ]
                    549: do_test vtab1-5-3 {
                    550:   filter $echo_module
                    551: } [list \
                    552:   xFilter {SELECT rowid, * FROM 't1'} \
                    553:   xFilter {SELECT rowid, * FROM 't2'} \
                    554:   xFilter {SELECT rowid, * FROM 't2'} \
                    555: ]
                    556: do_test vtab1-5-4 {
                    557:   set echo_module ""
                    558:   execsql {
                    559:     SELECT * FROM et1, et2 WHERE et2.d = 2;
                    560:   }
                    561: } [list \
                    562:   1 red green 2 hearts diamonds  \
                    563:   2 blue black 2 hearts diamonds \
                    564: ]
                    565: do_test vtab1-5-5 {
                    566:   filter $echo_module
                    567: } [list \
                    568:   xFilter {SELECT rowid, * FROM 't1'} \
                    569:   xFilter {SELECT rowid, * FROM 't2'} \
                    570:   xFilter {SELECT rowid, * FROM 't2'} \
                    571: ]
                    572: do_test vtab1-5-6 {
                    573:   execsql {
                    574:     CREATE INDEX i1 ON t2(d);
                    575:   }
                    576: 
                    577:   db close
                    578:   sqlite3 db test.db
                    579:   register_echo_module [sqlite3_connection_pointer db]
                    580: 
                    581:   set ::echo_module ""
                    582:   execsql {
                    583:     SELECT * FROM et1, et2 WHERE et2.d = 2;
                    584:   }
                    585: } [list \
                    586:   1 red green 2 hearts diamonds  \
                    587:   2 blue black 2 hearts diamonds \
                    588: ]
                    589: do_test vtab1-5-7 {
                    590:   filter $::echo_module
                    591: } [list \
                    592:   xFilter {SELECT rowid, * FROM 't2' WHERE d = ?} \
                    593:   xFilter {SELECT rowid, * FROM 't1'}             \
                    594: ]
                    595: 
                    596: execsql {
                    597:   DROP TABLE t1;
                    598:   DROP TABLE t2;
                    599:   DROP TABLE et1;
                    600:   DROP TABLE et2;
                    601: }
                    602: 
                    603: #----------------------------------------------------------------------
                    604: # Test cases vtab1-6 test INSERT, UPDATE and DELETE operations 
                    605: # on virtual tables.
                    606: do_test vtab1-6-1 {
                    607:   execsql { SELECT sql FROM sqlite_master }
                    608: } {}
                    609: do_test vtab1-6-2 {
                    610:   execsql {
                    611:     CREATE TABLE treal(a PRIMARY KEY, b, c);
                    612:     CREATE VIRTUAL TABLE techo USING echo(treal);
                    613:     SELECT name FROM sqlite_master WHERE type = 'table';
                    614:   }
                    615: } {treal techo}
                    616: do_test vtab1-6-3.1.1 {
                    617:   execsql {
                    618:     PRAGMA count_changes=ON;
                    619:     INSERT INTO techo VALUES(1, 2, 3);
                    620:   }
                    621: } {1}
                    622: do_test vtab1-6-3.1.2 {
                    623:   db changes
                    624: } {1}
                    625: do_test vtab1-6-3.2 {
                    626:   execsql {
                    627:     SELECT * FROM techo;
                    628:   }
                    629: } {1 2 3}
                    630: do_test vtab1-6-4.1 {
                    631:   execsql {
                    632:     UPDATE techo SET a = 5;
                    633:   }
                    634:   db changes
                    635: } {1}
                    636: do_test vtab1-6-4.2 {
                    637:   execsql {
                    638:     SELECT * FROM techo;
                    639:   }
                    640: } {5 2 3}
                    641: do_test vtab1-6-4.3 {
                    642:   execsql {
                    643:     UPDATE techo SET a=6 WHERE a<0;
                    644:   }
                    645:   db changes
                    646: } {0}
                    647: do_test vtab1-6-4.4 {
                    648:   execsql {
                    649:     SELECT * FROM techo;
                    650:   }
                    651: } {5 2 3}
                    652: 
                    653: do_test vtab1-6-5.1 {
                    654:  execsql {
                    655:    UPDATE techo set a = a||b||c;
                    656:  }
                    657:  db changes
                    658: } {1}
                    659: do_test vtab1-6-5.2 {
                    660:  execsql {
                    661:    SELECT * FROM techo;
                    662:  }
                    663: } {523 2 3}
                    664: 
                    665: do_test vtab1-6-6.1 {
                    666:   execsql {
                    667:     UPDATE techo set rowid = 10;
                    668:   }
                    669:   db changes
                    670: } {1}
                    671: do_test vtab1-6-6.2 {
                    672:   execsql {
                    673:     SELECT rowid FROM techo;
                    674:   }
                    675: } {10}
                    676: 
                    677: do_test vtab1-6-7.1.1 {
                    678:   execsql {
                    679:     INSERT INTO techo VALUES(11,12,13);
                    680:   }
                    681: } {1}
                    682: do_test vtab1-6-7.1.2 {
                    683:   db changes
                    684: } {1}
                    685: do_test vtab1-6-7.2 {
                    686:   execsql {
                    687:     SELECT * FROM techo ORDER BY a;
                    688:   }
                    689: } {11 12 13 523 2 3}
                    690: do_test vtab1-6-7.3 {
                    691:   execsql {
                    692:     UPDATE techo SET b=b+1000
                    693:   }
                    694:   db changes
                    695: } {2}
                    696: do_test vtab1-6-7.4 {
                    697:   execsql {
                    698:     SELECT * FROM techo ORDER BY a;
                    699:   }
                    700: } {11 1012 13 523 1002 3}
                    701: 
                    702: 
                    703: do_test vtab1-6-8.1 {
                    704:   execsql {
                    705:     DELETE FROM techo WHERE a=5;
                    706:   }
                    707:   db changes
                    708: } {0}
                    709: do_test vtab1-6-8.2 {
                    710:   execsql {
                    711:     SELECT * FROM techo ORDER BY a;
                    712:   }
                    713: } {11 1012 13 523 1002 3}
                    714: do_test vtab1-6-8.3 {
                    715:   execsql {
                    716:     DELETE FROM techo;
                    717:   }
                    718:   db changes
                    719: } {2}
                    720: do_test vtab1-6-8.4 {
                    721:   execsql {
                    722:     SELECT * FROM techo ORDER BY a;
                    723:   }
                    724: } {}
                    725: execsql {PRAGMA count_changes=OFF}
                    726: 
                    727: forcedelete test2.db
                    728: forcedelete test2.db-journal
                    729: sqlite3 db2 test2.db
                    730: execsql {
                    731:   CREATE TABLE techo(a PRIMARY KEY, b, c);
                    732: } db2
                    733: proc check_echo_table {tn} {
                    734:   set ::data1 [execsql {SELECT rowid, * FROM techo}]
                    735:   set ::data2 [execsql {SELECT rowid, * FROM techo} db2]
                    736:   do_test $tn {
                    737:     string equal $::data1 $::data2
                    738:   } 1
                    739: }
                    740: set tn 0
                    741: foreach stmt [list \
                    742:   {INSERT INTO techo VALUES('abc', 'def', 'ghi')}                        \
                    743:   {INSERT INTO techo SELECT a||'.'||rowid, b, c FROM techo}              \
                    744:   {INSERT INTO techo SELECT a||'x'||rowid, b, c FROM techo}              \
                    745:   {INSERT INTO techo SELECT a||'y'||rowid, b, c FROM techo}              \
                    746:   {DELETE FROM techo WHERE (oid % 3) = 0}                                \
                    747:   {UPDATE techo set rowid = 100 WHERE rowid = 1}                         \
                    748:   {INSERT INTO techo(a, b) VALUES('hello', 'world')}                     \
                    749:   {DELETE FROM techo}                                                    \
                    750: ] {
                    751:   execsql $stmt
                    752:   execsql $stmt db2
                    753:   check_echo_table vtab1-6.8.[incr tn]
                    754: }
                    755: 
                    756: db2 close
                    757: 
                    758: 
                    759: 
                    760: #----------------------------------------------------------------------
                    761: # Test cases vtab1-7 tests that the value returned by 
                    762: # sqlite3_last_insert_rowid() is set correctly when rows are inserted
                    763: # into virtual tables.
                    764: do_test vtab1.7-1 {
                    765:   execsql {
                    766:     CREATE TABLE real_abc(a PRIMARY KEY, b, c);
                    767:     CREATE VIRTUAL TABLE echo_abc USING echo(real_abc);
                    768:   }
                    769: } {}
                    770: do_test vtab1.7-2 {
                    771:   execsql {
                    772:     INSERT INTO echo_abc VALUES(1, 2, 3);
                    773:     SELECT last_insert_rowid();
                    774:   }
                    775: } {1}
                    776: do_test vtab1.7-3 {
                    777:   execsql {
                    778:     INSERT INTO echo_abc(rowid) VALUES(31427);
                    779:     SELECT last_insert_rowid();
                    780:   }
                    781: } {31427}
                    782: do_test vtab1.7-4 {
                    783:   execsql {
                    784:     INSERT INTO echo_abc SELECT a||'.v2', b, c FROM echo_abc;
                    785:     SELECT last_insert_rowid();
                    786:   }
                    787: } {31429}
                    788: do_test vtab1.7-5 {
                    789:   execsql {
                    790:     SELECT rowid, a, b, c FROM echo_abc
                    791:   }
                    792: } [list 1     1    2  3  \
                    793:         31427 {}   {} {} \
                    794:         31428 1.v2 2  3  \
                    795:         31429 {}  {} {}  \
                    796: ]
                    797: 
                    798: # Now test that DELETE and UPDATE operations do not modify the value.
                    799: do_test vtab1.7-6 {
                    800:   execsql {
                    801:     UPDATE echo_abc SET c = 5 WHERE b = 2;
                    802:     SELECT last_insert_rowid();
                    803:   }
                    804: } {31429}
                    805: do_test vtab1.7-7 {
                    806:   execsql {
                    807:     UPDATE echo_abc SET rowid = 5 WHERE rowid = 1;
                    808:     SELECT last_insert_rowid();
                    809:   }
                    810: } {31429}
                    811: do_test vtab1.7-8 {
                    812:   execsql {
                    813:     DELETE FROM echo_abc WHERE b = 2;
                    814:     SELECT last_insert_rowid();
                    815:   }
                    816: } {31429}
                    817: do_test vtab1.7-9 {
                    818:   execsql {
                    819:     SELECT rowid, a, b, c FROM echo_abc
                    820:   }
                    821: } [list 31427 {} {} {} \
                    822:         31429 {} {} {} \
                    823: ]
                    824: do_test vtab1.7-10 {
                    825:   execsql {
                    826:     DELETE FROM echo_abc WHERE b = 2;
                    827:     SELECT last_insert_rowid();
                    828:   }
                    829: } {31429}
                    830: do_test vtab1.7-11 {
                    831:   execsql {
                    832:     SELECT rowid, a, b, c FROM real_abc
                    833:   }
                    834: } [list 31427 {} {} {} \
                    835:         31429 {} {} {} \
                    836: ]
                    837: do_test vtab1.7-12 {
                    838:   execsql {
                    839:     DELETE FROM echo_abc;
                    840:     SELECT last_insert_rowid();
                    841:   }
                    842: } {31429}
                    843: do_test vtab1.7-13 {
                    844:   execsql {
                    845:     SELECT rowid, a, b, c FROM real_abc
                    846:   }
                    847: } {}
                    848: 
                    849: ifcapable attach {
                    850:   do_test vtab1.8-1 {
                    851:     set echo_module ""
                    852:     execsql {
                    853:       ATTACH 'test2.db' AS aux;
                    854:       CREATE VIRTUAL TABLE aux.e2 USING echo(real_abc);
                    855:     }
                    856:     set echo_module
                    857:   } [list xCreate echo aux e2 real_abc   \
                    858:           xSync   echo(real_abc)         \
                    859:           xCommit echo(real_abc)         \
                    860:   ]
                    861: }
                    862: do_test vtab1.8-2 {
                    863:   catchsql {
                    864:     DROP TABLE aux.e2;
                    865:   }
                    866:   execsql {
                    867:     DROP TABLE treal;
                    868:     DROP TABLE techo;
                    869:     DROP TABLE echo_abc;
                    870:     DROP TABLE real_abc;
                    871:   }
                    872: } {}
                    873: 
                    874: do_test vtab1.9-1 {
                    875:   set echo_module ""
                    876:   execsql {
                    877:     CREATE TABLE r(a, b, c);
                    878:     CREATE VIRTUAL TABLE e USING echo(r, e_log);
                    879:     SELECT name FROM sqlite_master;
                    880:   }
                    881: } {r e e_log}
                    882: do_test vtab1.9-2 {
                    883:   execsql {
                    884:     DROP TABLE e;
                    885:     SELECT name FROM sqlite_master;
                    886:   }
                    887: } {r}
                    888: 
                    889: do_test vtab1.9-3 {
                    890:   set echo_module ""
                    891:   execsql {
                    892:     CREATE VIRTUAL TABLE e USING echo(r, e_log, virtual 1 2 3 varchar(32));
                    893:   }
                    894:   set echo_module
                    895: } [list                                                        \
                    896:   xCreate echo main e r e_log {virtual 1 2 3 varchar(32)}      \
                    897:   xSync echo(r)                                                \
                    898:   xCommit echo(r)                                              \
                    899: ]
                    900: 
                    901: do_test vtab1.10-1 {
                    902:   execsql {
                    903:     CREATE TABLE del(d);
                    904:     CREATE VIRTUAL TABLE e2 USING echo(del);
                    905:   }
                    906:   db close
                    907:   sqlite3 db test.db
                    908:   register_echo_module [sqlite3_connection_pointer db]
                    909:   execsql {
                    910:     DROP TABLE del;
                    911:   }
                    912:   catchsql {
                    913:     SELECT * FROM e2;
                    914:   }
                    915: } {1 {vtable constructor failed: e2}}
                    916: do_test vtab1.10-2 {
                    917:   set rc [catch {
                    918:     set ptr [sqlite3_connection_pointer db]
                    919:     sqlite3_declare_vtab $ptr {CREATE TABLE abc(a, b, c)}
                    920:   } msg]
                    921:   list $rc $msg
                    922: } {1 {library routine called out of sequence}}
                    923: do_test vtab1.10-3 {
                    924:   set ::echo_module_begin_fail r
                    925:   catchsql {
                    926:     INSERT INTO e VALUES(1, 2, 3);
                    927:   }
                    928: } {1 {SQL logic error or missing database}}
                    929: do_test vtab1.10-4 {
                    930:   catch {execsql {
                    931:     EXPLAIN SELECT * FROM e WHERE rowid = 2;
                    932:     EXPLAIN QUERY PLAN SELECT * FROM e WHERE rowid = 2 ORDER BY rowid;
                    933:   }}
                    934: } {0}
                    935: 
                    936: do_test vtab1.10-5 {
                    937:   set echo_module ""
                    938:   execsql {
                    939:     SELECT * FROM e WHERE rowid||'' MATCH 'pattern';
                    940:   }
                    941:   set echo_module
                    942: } [list \
                    943:   xBestIndex {SELECT rowid, * FROM 'r'} \
                    944:   xFilter {SELECT rowid, * FROM 'r'}    \
                    945: ]
                    946: proc match_func {args} {return ""}
                    947: do_test vtab1.10-6 {
                    948:   set echo_module ""
                    949:   db function match match_func
                    950:   execsql {
                    951:     SELECT * FROM e WHERE match('pattern', rowid, 'pattern2');
                    952:   }
                    953:   set echo_module
                    954: } [list \
                    955:   xBestIndex {SELECT rowid, * FROM 'r'} \
                    956:   xFilter {SELECT rowid, * FROM 'r'}    \
                    957: ]
                    958: 
                    959: 
                    960: # Testing the xFindFunction interface
                    961: #
                    962: catch {rename ::echo_glob_overload {}}
                    963: do_test vtab1.11-1 {
                    964:   execsql {
                    965:     INSERT INTO r(a,b,c) VALUES(1,'?',99);
                    966:     INSERT INTO r(a,b,c) VALUES(2,3,99);
                    967:     SELECT a GLOB b FROM e
                    968:   }
                    969: } {1 0}
                    970: proc ::echo_glob_overload {a b} {
                    971:  return [list $b $a]
                    972: }
                    973: do_test vtab1.11-2 {
                    974:   execsql {
                    975:     SELECT a like 'b' FROM e
                    976:   }
                    977: } {0 0}
                    978: do_test vtab1.11-3 {
                    979:   execsql {
                    980:     SELECT a glob '2' FROM e
                    981:   }
                    982: } {{1 2} {2 2}}
                    983: do_test vtab1.11-4 {
                    984:   execsql {
                    985:     SELECT  glob('2',a) FROM e
                    986:   }
                    987: } {0 1}
                    988: do_test vtab1.11-5 {
                    989:   execsql {
                    990:     SELECT  glob(a,'2') FROM e
                    991:   }
                    992: } {{2 1} {2 2}}
                    993:  
                    994: #----------------------------------------------------------------------
                    995: # Test the outcome if a constraint is encountered half-way through
                    996: # a multi-row INSERT that is inside a transaction
                    997: #
                    998: do_test vtab1.12-1 {
                    999:   execsql {
                   1000:     CREATE TABLE b(a, b, c);
                   1001:     CREATE TABLE c(a UNIQUE, b, c);
                   1002:     INSERT INTO b VALUES(1, 'A', 'B');
                   1003:     INSERT INTO b VALUES(2, 'C', 'D');
                   1004:     INSERT INTO b VALUES(3, 'E', 'F');
                   1005:     INSERT INTO c VALUES(3, 'G', 'H');
                   1006:     CREATE VIRTUAL TABLE echo_c USING echo(c);
                   1007:   }
                   1008: } {}
                   1009: 
                   1010: # First test outside of a transaction.
                   1011: do_test vtab1.12-2 {
                   1012:   catchsql { INSERT INTO echo_c SELECT * FROM b; }
                   1013: } {1 {echo-vtab-error: column a is not unique}}
                   1014: do_test vtab1.12-2.1 {
                   1015:   sqlite3_errmsg db
                   1016: } {echo-vtab-error: column a is not unique}
                   1017: do_test vtab1.12-3 {
                   1018:   execsql { SELECT * FROM c }
                   1019: } {3 G H}
                   1020: 
                   1021: # Now the real test - wrapped in a transaction.
                   1022: do_test vtab1.12-4 {
                   1023:   execsql  {BEGIN}
                   1024:   catchsql { INSERT INTO echo_c SELECT * FROM b; }
                   1025: } {1 {echo-vtab-error: column a is not unique}}
                   1026: do_test vtab1.12-5 {
                   1027:   execsql { SELECT * FROM c }
                   1028: } {3 G H}
                   1029: do_test vtab1.12-6 {
                   1030:   execsql { COMMIT }
                   1031:   execsql { SELECT * FROM c }
                   1032: } {3 G H}
                   1033: 
                   1034: # At one point (ticket #2759), a WHERE clause of the form "<column> IS NULL"
                   1035: # on a virtual table was causing an assert() to fail in the compiler.
                   1036: #
                   1037: # "IS NULL" clauses should not be passed through to the virtual table
                   1038: # implementation. They are handled by SQLite after the vtab returns its
                   1039: # data.
                   1040: #
                   1041: do_test vtab1.13-1 {
                   1042:   execsql { 
                   1043:     SELECT * FROM echo_c WHERE a IS NULL 
                   1044:   }
                   1045: } {}
                   1046: do_test vtab1.13-2 {
                   1047:   execsql { 
                   1048:     INSERT INTO c VALUES(NULL, 15, 16);
                   1049:     SELECT * FROM echo_c WHERE a IS NULL 
                   1050:   }
                   1051: } {{} 15 16}
                   1052: do_test vtab1.13-3 {
                   1053:   execsql { 
                   1054:     INSERT INTO c VALUES(15, NULL, 16);
                   1055:     SELECT * FROM echo_c WHERE b IS NULL 
                   1056:   }
                   1057: } {15 {} 16}
                   1058: do_test vtab1.13-3 {
                   1059:   execsql { 
                   1060:     SELECT * FROM echo_c WHERE b IS NULL AND a = 15;
                   1061:   }
                   1062: } {15 {} 16}
                   1063: 
                   1064: 
                   1065: do_test vtab1-14.1 {
                   1066:   execsql { DELETE FROM c }
                   1067:   set echo_module ""
                   1068:   execsql { SELECT * FROM echo_c WHERE rowid IN (1, 2, 3) }
                   1069:   set echo_module
                   1070: } [list xBestIndex {SELECT rowid, * FROM 'c'} xFilter {SELECT rowid, * FROM 'c'}]
                   1071: 
                   1072: do_test vtab1-14.2 {
                   1073:   set echo_module ""
                   1074:   execsql { SELECT * FROM echo_c WHERE rowid = 1 }
                   1075:   set echo_module
                   1076: } [list xBestIndex {SELECT rowid, * FROM 'c' WHERE rowid = ?} xFilter {SELECT rowid, * FROM 'c' WHERE rowid = ?} 1]
                   1077: 
                   1078: do_test vtab1-14.3 {
                   1079:   set echo_module ""
                   1080:   execsql { SELECT * FROM echo_c WHERE a = 1 }
                   1081:   set echo_module
                   1082: } [list xBestIndex {SELECT rowid, * FROM 'c' WHERE a = ?} xFilter {SELECT rowid, * FROM 'c' WHERE a = ?} 1]
                   1083: 
                   1084: do_test vtab1-14.4 {
                   1085:   set echo_module ""
                   1086:   execsql { SELECT * FROM echo_c WHERE a IN (1, 2) }
                   1087:   set echo_module
                   1088: } [list xBestIndex {SELECT rowid, * FROM 'c'} xFilter {SELECT rowid, * FROM 'c'}]
                   1089: 
                   1090: do_test vtab1-15.1 {
                   1091:   execsql {
                   1092:     CREATE TABLE t1(a, b, c);
                   1093:     CREATE VIRTUAL TABLE echo_t1 USING echo(t1);
                   1094:   }
                   1095: } {}
                   1096: do_test vtab1-15.2 {
                   1097:   execsql {
                   1098:     INSERT INTO echo_t1(rowid) VALUES(45);
                   1099:     SELECT rowid, * FROM echo_t1;
                   1100:   }
                   1101: } {45 {} {} {}}
                   1102: do_test vtab1-15.3 {
                   1103:   execsql {
                   1104:     INSERT INTO echo_t1(rowid) VALUES(NULL);
                   1105:     SELECT rowid, * FROM echo_t1;
                   1106:   }
                   1107: } {45 {} {} {} 46 {} {} {}}
                   1108: do_test vtab1-15.4 {
                   1109:   catchsql {
                   1110:     INSERT INTO echo_t1(rowid) VALUES('new rowid');
                   1111:   }
                   1112: } {1 {datatype mismatch}}
                   1113: 
                   1114: # The following tests - vtab1-16.* - are designed to test that setting 
                   1115: # sqlite3_vtab.zErrMsg variable can be used by the vtab interface to 
                   1116: # return an error message to the user.
                   1117: # 
                   1118: do_test vtab1-16.1 {
                   1119:   execsql {
                   1120:     CREATE TABLE t2(a PRIMARY KEY, b, c);
                   1121:     INSERT INTO t2 VALUES(1, 2, 3);
                   1122:     INSERT INTO t2 VALUES(4, 5, 6);
                   1123:     CREATE VIRTUAL TABLE echo_t2 USING echo(t2);
                   1124:   }
                   1125: } {}
                   1126: 
                   1127: set tn 2
                   1128: foreach method [list \
                   1129:     xBestIndex       \
                   1130:     xOpen            \
                   1131:     xFilter          \
                   1132:     xNext            \
                   1133:     xColumn          \
                   1134:     xRowid           \
                   1135: ] {
                   1136:   do_test vtab1-16.$tn {
                   1137:     set echo_module_fail($method,t2) "the $method method has failed"
                   1138:     catchsql { SELECT rowid, * FROM echo_t2 WHERE a >= 1 }
                   1139:   } "1 {echo-vtab-error: the $method method has failed}"
                   1140:   unset echo_module_fail($method,t2)
                   1141:   incr tn
                   1142: }
                   1143: 
                   1144: foreach method [list \
                   1145:   xUpdate            \
                   1146:   xBegin             \
                   1147:   xSync              \
                   1148: ] {
                   1149:   do_test vtab1-16.$tn {
                   1150:     set echo_module_fail($method,t2) "the $method method has failed"
                   1151:     catchsql { INSERT INTO echo_t2 VALUES(7, 8, 9) }
                   1152:   } "1 {echo-vtab-error: the $method method has failed}"
                   1153:   unset echo_module_fail($method,t2)
                   1154:   incr tn
                   1155: }
                   1156: 
                   1157: ifcapable altertable {
                   1158:   do_test vtab1-16.$tn {
                   1159:     set echo_module_fail(xRename,t2) "the xRename method has failed"
                   1160:     catchsql { ALTER TABLE echo_t2 RENAME TO another_name }
                   1161:   } "1 {echo-vtab-error: the xRename method has failed}"
                   1162:   unset echo_module_fail(xRename,t2)
                   1163:   incr tn
                   1164: }
                   1165: 
                   1166: # The following test case exposes an instance in sqlite3_declare_vtab()
                   1167: # an error message was set using a call similar to sqlite3_mprintf(zErr),
                   1168: # where zErr is an arbitrary string. This is no good if the string contains
                   1169: # characters that can be mistaken for printf() formatting directives.
                   1170: #
                   1171: do_test vtab1-17.1 {
                   1172:   execsql { 
                   1173:     PRAGMA writable_schema = 1;
                   1174:     INSERT INTO sqlite_master VALUES(
                   1175:       'table', 't3', 't3', 0, 'INSERT INTO "%s%s" VALUES(1)'
                   1176:     );
                   1177:   }
                   1178:   catchsql { CREATE VIRTUAL TABLE t4 USING echo(t3); }
                   1179: } {1 {vtable constructor failed: t4}}
                   1180: 
                   1181: # This test verifies that ticket 48f29963 is fixed.
                   1182: #
                   1183: do_test vtab1-17.1 {
                   1184:   execsql { 
                   1185:     CREATE TABLE t5(a, b);
                   1186:     CREATE VIRTUAL TABLE e5 USING echo_v2(t5);
                   1187:     BEGIN;
                   1188:       INSERT INTO e5 VALUES(1, 2);
                   1189:       DROP TABLE e5;
                   1190:       SAVEPOINT one;
                   1191:       ROLLBACK TO one;
                   1192:     COMMIT;
                   1193:   }
                   1194: } {}
                   1195: 
                   1196: unset -nocomplain echo_module_begin_fail
                   1197: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>