File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / shared.test
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:16 2012 UTC (12 years, 10 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    1: # 2005 December 30
    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: #
   12: # $Id: shared.test,v 1.1.1.1 2012/02/21 17:04:16 misho Exp $
   13: 
   14: set testdir [file dirname $argv0]
   15: source $testdir/tester.tcl
   16: db close
   17: 
   18: # These tests cannot be run without the ATTACH command.
   19: #
   20: ifcapable !shared_cache||!attach {
   21:   finish_test
   22:   return
   23: }
   24: 
   25: set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
   26: 
   27: foreach av [list 0 1] {
   28: 
   29: # Open the database connection and execute the auto-vacuum pragma
   30: forcedelete test.db
   31: sqlite3 db test.db
   32: 
   33: ifcapable autovacuum {
   34:   do_test shared-[expr $av+1].1.0 {
   35:     execsql "pragma auto_vacuum=$::av"
   36:     execsql {pragma auto_vacuum}
   37:   } "$av"
   38: } else {
   39:   if {$av} {
   40:     db close
   41:     break
   42:   }
   43: }
   44: 
   45: # if we're using proxy locks, we use 2 filedescriptors for a db
   46: # that is open but NOT yet locked, after a lock is taken we'll have 3, 
   47: # normally sqlite uses 1 (proxy locking adds the conch and the local lock)
   48: set using_proxy 0
   49: foreach {name value} [array get env SQLITE_FORCE_PROXY_LOCKING] {
   50:   set using_proxy $value
   51: }
   52: set extrafds_prelock 0
   53: set extrafds_postlock 0
   54: if {$using_proxy>0} {
   55:   set extrafds_prelock 1
   56:   set extrafds_postlock 2
   57: } 
   58: 
   59: # $av is currently 0 if this loop iteration is to test with auto-vacuum turned
   60: # off, and 1 if it is turned on. Increment it so that (1 -> no auto-vacuum) 
   61: # and (2 -> auto-vacuum). The sole reason for this is so that it looks nicer
   62: # when we use this variable as part of test-case names.
   63: #
   64: incr av
   65: 
   66: # Test organization:
   67: #
   68: # shared-1.*: Simple test to verify basic sanity of table level locking when
   69: #             two connections share a pager cache.
   70: # shared-2.*: Test that a read transaction can co-exist with a 
   71: #             write-transaction, including a simple test to ensure the 
   72: #             external locking protocol is still working.
   73: # shared-3.*: Simple test of read-uncommitted mode.
   74: # shared-4.*: Check that the schema is locked and unlocked correctly.
   75: # shared-5.*: Test that creating/dropping schema items works when databases
   76: #             are attached in different orders to different handles.
   77: # shared-6.*: Locking, UNION ALL queries and sub-queries.
   78: # shared-7.*: Autovacuum and shared-cache.
   79: # shared-8.*: Tests related to the text encoding of shared-cache databases.
   80: # shared-9.*: TEMP triggers and shared-cache databases.
   81: # shared-10.*: Tests of sqlite3_close().
   82: # shared-11.*: Test transaction locking.
   83: #
   84: 
   85: do_test shared-$av.1.1 {
   86:   # Open a second database on the file test.db. It should use the same pager
   87:   # cache and schema as the original connection. Verify that only 1 file is 
   88:   # opened.
   89:   sqlite3 db2 test.db
   90:   set ::sqlite_open_file_count
   91:   expr $sqlite_open_file_count-$extrafds_postlock
   92: } {1}
   93: do_test shared-$av.1.2 {
   94:   # Add a table and a single row of data via the first connection. 
   95:   # Ensure that the second connection can see them.
   96:   execsql {
   97:     CREATE TABLE abc(a, b, c);
   98:     INSERT INTO abc VALUES(1, 2, 3);
   99:   } db
  100:   execsql {
  101:     SELECT * FROM abc;
  102:   } db2
  103: } {1 2 3}
  104: do_test shared-$av.1.3 {
  105:   # Have the first connection begin a transaction and obtain a read-lock
  106:   # on table abc. This should not prevent the second connection from 
  107:   # querying abc.
  108:   execsql {
  109:     BEGIN;
  110:     SELECT * FROM abc;
  111:   }
  112:   execsql {
  113:     SELECT * FROM abc;
  114:   } db2
  115: } {1 2 3}
  116: do_test shared-$av.1.4 {
  117:   # Try to insert a row into abc via connection 2. This should fail because
  118:   # of the read-lock connection 1 is holding on table abc (obtained in the
  119:   # previous test case).
  120:   catchsql {
  121:     INSERT INTO abc VALUES(4, 5, 6);
  122:   } db2
  123: } {1 {database table is locked: abc}}
  124: do_test shared-$av.1.5 {
  125:   # Using connection 2 (the one without the open transaction), try to create
  126:   # a new table. This should fail because of the open read transaction 
  127:   # held by connection 1.
  128:   catchsql {
  129:     CREATE TABLE def(d, e, f);
  130:   } db2
  131: } {1 {database table is locked: sqlite_master}}
  132: do_test shared-$av.1.6 {
  133:   # Upgrade connection 1's transaction to a write transaction. Create
  134:   # a new table - def - and insert a row into it. Because the connection 1
  135:   # transaction modifies the schema, it should not be possible for 
  136:   # connection 2 to access the database at all until the connection 1 
  137:   # has finished the transaction.
  138:   execsql {
  139:     CREATE TABLE def(d, e, f);
  140:     INSERT INTO def VALUES('IV', 'V', 'VI');
  141:   }
  142: } {}
  143: do_test shared-$av.1.7 {
  144:   # Read from the sqlite_master table with connection 1 (inside the 
  145:   # transaction). Then test that we can not do this with connection 2. This
  146:   # is because of the schema-modified lock established by connection 1 
  147:   # in the previous test case.
  148:   execsql {
  149:     SELECT * FROM sqlite_master;
  150:   }
  151:   catchsql {
  152:     SELECT * FROM sqlite_master;
  153:   } db2
  154: } {1 {database schema is locked: main}}
  155: do_test shared-$av.1.8 {
  156:   # Commit the connection 1 transaction.
  157:   execsql {
  158:     COMMIT;
  159:   }
  160: } {}
  161: 
  162: do_test shared-$av.2.1 {
  163:   # Open connection db3 to the database. Use a different path to the same
  164:   # file so that db3 does *not* share the same pager cache as db and db2
  165:   # (there should be two open file handles).
  166:   if {$::tcl_platform(platform)=="unix"} {
  167:     sqlite3 db3 ./test.db
  168:   } else {
  169:     sqlite3 db3 TEST.DB
  170:   }
  171:   set ::sqlite_open_file_count
  172:   expr $sqlite_open_file_count-($extrafds_prelock+$extrafds_postlock)
  173: } {2}
  174: do_test shared-$av.2.2 {
  175:   # Start read transactions on db and db2 (the shared pager cache). Ensure
  176:   # db3 cannot write to the database.
  177:   execsql {
  178:     BEGIN;
  179:     SELECT * FROM abc;
  180:   }
  181:   execsql {
  182:     BEGIN;
  183:     SELECT * FROM abc;
  184:   } db2
  185:   catchsql {
  186:     INSERT INTO abc VALUES(1, 2, 3);
  187:   } db2
  188: } {1 {database table is locked: abc}}
  189: do_test shared-$av.2.3 {
  190:   # Turn db's transaction into a write-transaction. db3 should still be
  191:   # able to read from table def (but will not see the new row). Connection
  192:   # db2 should not be able to read def (because of the write-lock).
  193: 
  194: # Todo: The failed "INSERT INTO abc ..." statement in the above test
  195: # has started a write-transaction on db2 (should this be so?). This 
  196: # would prevent connection db from starting a write-transaction. So roll the
  197: # db2 transaction back and replace it with a new read transaction.
  198:   execsql {
  199:     ROLLBACK;
  200:     BEGIN;
  201:     SELECT * FROM abc;
  202:   } db2
  203: 
  204:   execsql {
  205:     INSERT INTO def VALUES('VII', 'VIII', 'IX');
  206:   }
  207:   concat [
  208:     catchsql { SELECT * FROM def; } db3
  209:   ] [
  210:     catchsql { SELECT * FROM def; } db2
  211:   ]
  212: } {0 {IV V VI} 1 {database table is locked: def}}
  213: do_test shared-$av.2.4 {
  214:   # Commit the open transaction on db. db2 still holds a read-transaction.
  215:   # This should prevent db3 from writing to the database, but not from 
  216:   # reading.
  217:   execsql {
  218:     COMMIT;
  219:   }
  220:   concat [
  221:     catchsql { SELECT * FROM def; } db3
  222:   ] [
  223:     catchsql { INSERT INTO def VALUES('X', 'XI', 'XII'); } db3
  224:   ]
  225: } {0 {IV V VI VII VIII IX} 1 {database is locked}}
  226: 
  227: catchsql COMMIT db2
  228: 
  229: do_test shared-$av.3.1.1 {
  230:   # This test case starts a linear scan of table 'seq' using a 
  231:   # read-uncommitted connection. In the middle of the scan, rows are added
  232:   # to the end of the seq table (ahead of the current cursor position).
  233:   # The uncommitted rows should be included in the results of the scan.
  234:   execsql "
  235:     CREATE TABLE seq(i PRIMARY KEY, x);
  236:     INSERT INTO seq VALUES(1, '[string repeat X 500]');
  237:     INSERT INTO seq VALUES(2, '[string repeat X 500]');
  238:   "
  239:   execsql {SELECT * FROM sqlite_master} db2
  240:   execsql {PRAGMA read_uncommitted = 1} db2
  241: 
  242:   set ret [list]
  243:   db2 eval {SELECT i FROM seq ORDER BY i} {
  244:     if {$i < 4} {
  245:       set max [execsql {SELECT max(i) FROM seq}]
  246:       db eval {
  247:         INSERT INTO seq SELECT i + :max, x FROM seq;
  248:       }
  249:     }
  250:     lappend ret $i
  251:   }
  252:   set ret
  253: } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
  254: do_test shared-$av.3.1.2 {
  255:   # Another linear scan through table seq using a read-uncommitted connection.
  256:   # This time, delete each row as it is read. Should not affect the results of
  257:   # the scan, but the table should be empty after the scan is concluded 
  258:   # (test 3.1.3 verifies this).
  259:   set ret [list]
  260:   db2 eval {SELECT i FROM seq} {
  261:     db eval {DELETE FROM seq WHERE i = :i}
  262:     lappend ret $i
  263:   }
  264:   set ret
  265: } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
  266: do_test shared-$av.3.1.3 {
  267:   execsql {
  268:     SELECT * FROM seq;
  269:   }
  270: } {}
  271: 
  272: catch {db close}
  273: catch {db2 close}
  274: catch {db3 close}
  275: 
  276: #--------------------------------------------------------------------------
  277: # Tests shared-4.* test that the schema locking rules are applied 
  278: # correctly. i.e.:
  279: #
  280: # 1. All transactions require a read-lock on the schemas of databases they
  281: #    access.
  282: # 2. Transactions that modify a database schema require a write-lock on that
  283: #    schema.
  284: # 3. It is not possible to compile a statement while another handle has a 
  285: #    write-lock on the schema.
  286: #
  287: 
  288: # Open two database handles db and db2. Each has a single attach database
  289: # (as well as main):
  290: #
  291: #     db.main   ->   ./test.db
  292: #     db.test2  ->   ./test2.db
  293: #     db2.main  ->   ./test2.db
  294: #     db2.test  ->   ./test.db
  295: #
  296: forcedelete test.db
  297: forcedelete test2.db
  298: forcedelete test2.db-journal
  299: sqlite3 db  test.db
  300: sqlite3 db2 test2.db
  301: do_test shared-$av.4.1.1 {
  302:   set sqlite_open_file_count
  303:   expr $sqlite_open_file_count-($extrafds_prelock*2)
  304: } {2}
  305: do_test shared-$av.4.1.2 {
  306:   execsql {ATTACH 'test2.db' AS test2}
  307:   set sqlite_open_file_count
  308:   expr $sqlite_open_file_count-($extrafds_postlock*2)
  309: } {2}
  310: do_test shared-$av.4.1.3 {
  311:   execsql {ATTACH 'test.db' AS test} db2
  312:   set sqlite_open_file_count
  313:   expr $sqlite_open_file_count-($extrafds_postlock*2)
  314: } {2}
  315: 
  316: # Sanity check: Create a table in ./test.db via handle db, and test that handle
  317: # db2 can "see" the new table immediately. A handle using a seperate pager
  318: # cache would have to reload the database schema before this were possible.
  319: #
  320: do_test shared-$av.4.2.1 {
  321:   execsql {
  322:     CREATE TABLE abc(a, b, c);
  323:     CREATE TABLE def(d, e, f);
  324:     INSERT INTO abc VALUES('i', 'ii', 'iii');
  325:     INSERT INTO def VALUES('I', 'II', 'III');
  326:   }
  327: } {}
  328: do_test shared-$av.4.2.2 {
  329:   execsql {
  330:     SELECT * FROM test.abc;
  331:   } db2
  332: } {i ii iii}
  333: 
  334: # Open a read-transaction and read from table abc via handle 2. Check that
  335: # handle 1 can read table abc. Check that handle 1 cannot modify table abc
  336: # or the database schema. Then check that handle 1 can modify table def.
  337: #
  338: do_test shared-$av.4.3.1 {
  339:   execsql {
  340:     BEGIN;
  341:     SELECT * FROM test.abc;
  342:   } db2
  343: } {i ii iii}
  344: do_test shared-$av.4.3.2 {
  345:   catchsql {
  346:     INSERT INTO abc VALUES('iv', 'v', 'vi');
  347:   }
  348: } {1 {database table is locked: abc}}
  349: do_test shared-$av.4.3.3 {
  350:   catchsql {
  351:     CREATE TABLE ghi(g, h, i);
  352:   }
  353: } {1 {database table is locked: sqlite_master}}
  354: do_test shared-$av.4.3.3 {
  355:   catchsql {
  356:     INSERT INTO def VALUES('IV', 'V', 'VI');
  357:   }
  358: } {0 {}}
  359: do_test shared-$av.4.3.4 {
  360:   # Cleanup: commit the transaction opened by db2.
  361:   execsql {
  362:     COMMIT
  363:   } db2
  364: } {}
  365: 
  366: # Open a write-transaction using handle 1 and modify the database schema.
  367: # Then try to execute a compiled statement to read from the same 
  368: # database via handle 2 (fails to get the lock on sqlite_master). Also
  369: # try to compile a read of the same database using handle 2 (also fails).
  370: # Finally, compile a read of the other database using handle 2. This
  371: # should also fail.
  372: #
  373: ifcapable compound {
  374:   do_test shared-$av.4.4.1.2 {
  375:     # Sanity check 1: Check that the schema is what we think it is when viewed
  376:     # via handle 1.
  377:     execsql {
  378:       CREATE TABLE test2.ghi(g, h, i);
  379:       SELECT 'test.db:'||name FROM sqlite_master 
  380:       UNION ALL
  381:       SELECT 'test2.db:'||name FROM test2.sqlite_master;
  382:     }
  383:   } {test.db:abc test.db:def test2.db:ghi}
  384:   do_test shared-$av.4.4.1.2 {
  385:     # Sanity check 2: Check that the schema is what we think it is when viewed
  386:     # via handle 2.
  387:     execsql {
  388:       SELECT 'test2.db:'||name FROM sqlite_master 
  389:       UNION ALL
  390:       SELECT 'test.db:'||name FROM test.sqlite_master;
  391:     } db2
  392:   } {test2.db:ghi test.db:abc test.db:def}
  393: }
  394: 
  395: do_test shared-$av.4.4.2 {
  396:   set ::DB2 [sqlite3_connection_pointer db2]
  397:   set sql {SELECT * FROM abc}
  398:   set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
  399:   execsql {
  400:     BEGIN;
  401:     CREATE TABLE jkl(j, k, l);
  402:   }
  403:   sqlite3_step $::STMT1
  404: } {SQLITE_ERROR}
  405: do_test shared-$av.4.4.3 {
  406:   sqlite3_finalize $::STMT1
  407: } {SQLITE_LOCKED}
  408: do_test shared-$av.4.4.4 {
  409:   set rc [catch {
  410:     set ::STMT1 [sqlite3_prepare $::DB2 $sql -1 DUMMY]
  411:   } msg]
  412:   list $rc $msg
  413: } {1 {(6) database schema is locked: test}}
  414: do_test shared-$av.4.4.5 {
  415:   set rc [catch {
  416:     set ::STMT1 [sqlite3_prepare $::DB2 "SELECT * FROM ghi" -1 DUMMY]
  417:   } msg]
  418:   list $rc $msg
  419: } {1 {(6) database schema is locked: test}}
  420: 
  421: 
  422: catch {db2 close}
  423: catch {db close}
  424: 
  425: #--------------------------------------------------------------------------
  426: # Tests shared-5.* 
  427: #
  428: foreach db [list test.db test1.db test2.db test3.db] {
  429:   forcedelete $db ${db}-journal
  430: }
  431: do_test shared-$av.5.1.1 {
  432:   sqlite3 db1 test.db
  433:   sqlite3 db2 test.db
  434:   execsql {
  435:     ATTACH 'test1.db' AS test1;
  436:     ATTACH 'test2.db' AS test2;
  437:     ATTACH 'test3.db' AS test3;
  438:   } db1
  439:   execsql {
  440:     ATTACH 'test3.db' AS test3;
  441:     ATTACH 'test2.db' AS test2;
  442:     ATTACH 'test1.db' AS test1;
  443:   } db2
  444: } {}
  445: do_test shared-$av.5.1.2 {
  446:   execsql {
  447:     CREATE TABLE test1.t1(a, b);
  448:     CREATE INDEX test1.i1 ON t1(a, b);
  449:   } db1
  450: } {}
  451: ifcapable view {
  452:   do_test shared-$av.5.1.3 {
  453:     execsql {
  454:       CREATE VIEW test1.v1 AS SELECT * FROM t1;
  455:     } db1
  456:   } {}
  457: }
  458: ifcapable trigger {
  459:   do_test shared-$av.5.1.4 {
  460:     execsql {
  461:       CREATE TRIGGER test1.trig1 AFTER INSERT ON t1 BEGIN
  462:         INSERT INTO t1 VALUES(new.a, new.b);
  463:       END;
  464:     } db1
  465:   } {}
  466: }
  467: do_test shared-$av.5.1.5 {
  468:   execsql {
  469:     DROP INDEX i1;
  470:   } db2
  471: } {}
  472: ifcapable view {
  473:   do_test shared-$av.5.1.6 {
  474:     execsql {
  475:       DROP VIEW v1;
  476:     } db2
  477:   } {}
  478: }
  479: ifcapable trigger {
  480:   do_test shared-$av.5.1.7 {
  481:     execsql {
  482:       DROP TRIGGER trig1;
  483:     } db2
  484:   } {}
  485: }
  486: do_test shared-$av.5.1.8 {
  487:   execsql {
  488:     DROP TABLE t1;
  489:   } db2
  490: } {}
  491: ifcapable compound {
  492:   do_test shared-$av.5.1.9 {
  493:     execsql {
  494:       SELECT * FROM sqlite_master UNION ALL SELECT * FROM test1.sqlite_master
  495:     } db1
  496:   } {}
  497: }
  498: 
  499: #--------------------------------------------------------------------------
  500: # Tests shared-6.* test that a query obtains all the read-locks it needs
  501: # before starting execution of the query. This means that there is no chance
  502: # some rows of data will be returned before a lock fails and SQLITE_LOCK
  503: # is returned.
  504: #
  505: do_test shared-$av.6.1.1 {
  506:   execsql {
  507:     CREATE TABLE t1(a, b);
  508:     CREATE TABLE t2(a, b);
  509:     INSERT INTO t1 VALUES(1, 2);
  510:     INSERT INTO t2 VALUES(3, 4);
  511:   } db1
  512: } {}
  513: ifcapable compound {
  514:   do_test shared-$av.6.1.2 {
  515:     execsql {
  516:       SELECT * FROM t1 UNION ALL SELECT * FROM t2;
  517:     } db2
  518:   } {1 2 3 4}
  519: }
  520: do_test shared-$av.6.1.3 {
  521:   # Establish a write lock on table t2 via connection db2. Then make a 
  522:   # UNION all query using connection db1 that first accesses t1, followed 
  523:   # by t2. If the locks are grabbed at the start of the statement (as 
  524:   # they should be), no rows are returned. If (as was previously the case)
  525:   # they are grabbed as the tables are accessed, the t1 rows will be 
  526:   # returned before the query fails.
  527:   #
  528:   execsql {
  529:     BEGIN;
  530:     INSERT INTO t2 VALUES(5, 6);
  531:   } db2
  532:   set ret [list]
  533:   catch {
  534:     db1 eval {SELECT * FROM t1 UNION ALL SELECT * FROM t2} {
  535:       lappend ret $a $b
  536:     }
  537:   }
  538:   set ret
  539: } {}
  540: do_test shared-$av.6.1.4 {
  541:   execsql {
  542:     COMMIT;
  543:     BEGIN;
  544:     INSERT INTO t1 VALUES(7, 8);
  545:   } db2
  546:   set ret [list]
  547:   catch {
  548:     db1 eval {
  549:       SELECT (CASE WHEN a>4 THEN (SELECT a FROM t1) ELSE 0 END) AS d FROM t2;
  550:     } {
  551:       lappend ret $d
  552:     }
  553:   }
  554:   set ret
  555: } {}
  556: 
  557: catch {db1 close}
  558: catch {db2 close}
  559: foreach f [list test.db test2.db] {
  560:   forcedelete $f ${f}-journal
  561: }
  562: 
  563: #--------------------------------------------------------------------------
  564: # Tests shared-7.* test auto-vacuum does not invalidate cursors from
  565: # other shared-cache users when it reorganizes the database on 
  566: # COMMIT.
  567: #
  568: do_test shared-$av.7.1 {
  569:   # This test case sets up a test database in auto-vacuum mode consisting 
  570:   # of two tables, t1 and t2. Both have a single index. Table t1 is 
  571:   # populated first (so consists of pages toward the start of the db file), 
  572:   # t2 second (pages toward the end of the file). 
  573:   sqlite3 db test.db
  574:   sqlite3 db2 test.db
  575:   execsql {
  576:     BEGIN;
  577:     CREATE TABLE t1(a PRIMARY KEY, b);
  578:     CREATE TABLE t2(a PRIMARY KEY, b);
  579:   }
  580:   set ::contents {}
  581:   for {set i 0} {$i < 100} {incr i} {
  582:     set a [string repeat "$i " 20]
  583:     set b [string repeat "$i " 20]
  584:     db eval {
  585:       INSERT INTO t1 VALUES(:a, :b);
  586:     }
  587:     lappend ::contents [list [expr $i+1] $a $b]
  588:   }
  589:   execsql {
  590:     INSERT INTO t2 SELECT * FROM t1;
  591:     COMMIT;
  592:   }
  593: } {}
  594: do_test shared-$av.7.2 {
  595:   # This test case deletes the contents of table t1 (the one at the start of
  596:   # the file) while many cursors are open on table t2 and its index. All of
  597:   # the non-root pages will be moved from the end to the start of the file
  598:   # when the DELETE is committed - this test verifies that moving the pages
  599:   # does not disturb the open cursors.
  600:   #
  601: 
  602:   proc lockrow {db tbl oids body} {
  603:     set ret [list]
  604:     db eval "SELECT oid AS i, a, b FROM $tbl ORDER BY a" {
  605:       if {$i==[lindex $oids 0]} {
  606:         set noids [lrange $oids 1 end]
  607:         if {[llength $noids]==0} {
  608:           set subret [eval $body]
  609:         } else {
  610:           set subret [lockrow $db $tbl $noids $body]
  611:         }
  612:       }
  613:       lappend ret [list $i $a $b]
  614:     }
  615:     return [linsert $subret 0 $ret]
  616:   }
  617:   proc locktblrows {db tbl body} {
  618:     set oids [db eval "SELECT oid FROM $tbl"]
  619:     lockrow $db $tbl $oids $body
  620:   }
  621: 
  622:   set scans [locktblrows db t2 {
  623:     execsql {
  624:       DELETE FROM t1;
  625:     } db2
  626:   }]
  627:   set error 0
  628: 
  629:   # Test that each SELECT query returned the expected contents of t2.
  630:   foreach s $scans {
  631:     if {[lsort -integer -index 0 $s]!=$::contents} {
  632:       set error 1
  633:     }
  634:   }
  635:   set error
  636: } {0}
  637: 
  638: catch {db close}
  639: catch {db2 close}
  640: unset -nocomplain contents
  641: 
  642: #--------------------------------------------------------------------------
  643: # The following tests try to trick the shared-cache code into assuming
  644: # the wrong encoding for a database.
  645: #
  646: forcedelete test.db test.db-journal
  647: ifcapable utf16 {
  648:   do_test shared-$av.8.1.1 {
  649:     sqlite3 db test.db
  650:     execsql {
  651:       PRAGMA encoding = 'UTF-16';
  652:       SELECT * FROM sqlite_master;
  653:     }
  654:   } {}
  655:   do_test shared-$av.8.1.2 {
  656:     string range [execsql {PRAGMA encoding;}] 0 end-2
  657:   } {UTF-16}
  658: 
  659:   do_test shared-$av.8.1.3 {
  660:     sqlite3 db2 test.db
  661:     execsql {
  662:       PRAGMA encoding = 'UTF-8';
  663:       CREATE TABLE abc(a, b, c);
  664:     } db2
  665:   } {}
  666:   do_test shared-$av.8.1.4 {
  667:     execsql {
  668:       SELECT * FROM sqlite_master;
  669:     }
  670:   } "table abc abc [expr $AUTOVACUUM?3:2] {CREATE TABLE abc(a, b, c)}"
  671:   do_test shared-$av.8.1.5 {
  672:     db2 close
  673:     execsql {
  674:       PRAGMA encoding;
  675:     }
  676:   } {UTF-8}
  677: 
  678:   forcedelete test2.db test2.db-journal
  679:   do_test shared-$av.8.2.1 {
  680:     execsql {
  681:       ATTACH 'test2.db' AS aux;
  682:       SELECT * FROM aux.sqlite_master;
  683:     }
  684:   } {}
  685:   do_test shared-$av.8.2.2 {
  686:     sqlite3 db2 test2.db
  687:     execsql {
  688:       PRAGMA encoding = 'UTF-16';
  689:       CREATE TABLE def(d, e, f);
  690:     } db2
  691:     string range [execsql {PRAGMA encoding;} db2] 0 end-2
  692:   } {UTF-16}
  693: 
  694:   catch {db close}
  695:   catch {db2 close}
  696:   forcedelete test.db test2.db
  697: 
  698:   do_test shared-$av.8.3.2 {
  699:     sqlite3 db test.db
  700:     execsql { CREATE TABLE def(d, e, f) }
  701:     execsql { PRAGMA encoding }
  702:   } {UTF-8}
  703:   do_test shared-$av.8.3.3 {
  704:     set zDb16 "[encoding convertto unicode test.db]\x00\x00"
  705:     set db16 [sqlite3_open16 $zDb16 {}]
  706: 
  707:     set stmt [sqlite3_prepare $db16 "SELECT sql FROM sqlite_master" -1 DUMMY]
  708:     sqlite3_step $stmt
  709:     set sql [sqlite3_column_text $stmt 0]
  710:     sqlite3_finalize $stmt
  711:     set sql
  712:   } {CREATE TABLE def(d, e, f)}
  713:   do_test shared-$av.8.3.4 {
  714:     set stmt [sqlite3_prepare $db16 "PRAGMA encoding" -1 DUMMY]
  715:     sqlite3_step $stmt
  716:     set enc [sqlite3_column_text $stmt 0]
  717:     sqlite3_finalize $stmt
  718:     set enc
  719:   } {UTF-8}
  720: 
  721:   sqlite3_close $db16
  722: 
  723: # Bug #2547 is causing this to fail.
  724: if 0 {
  725:   do_test shared-$av.8.2.3 {
  726:     catchsql {
  727:       SELECT * FROM aux.sqlite_master;
  728:     }
  729:   } {1 {attached databases must use the same text encoding as main database}}
  730: }
  731: }
  732: 
  733: catch {db close}
  734: catch {db2 close}
  735: forcedelete test.db test2.db
  736: 
  737: #---------------------------------------------------------------------------
  738: # The following tests - shared-9.* - test interactions between TEMP triggers
  739: # and shared-schemas.
  740: #
  741: ifcapable trigger&&tempdb {
  742: 
  743: do_test shared-$av.9.1 {
  744:   sqlite3 db test.db
  745:   sqlite3 db2 test.db
  746:   execsql {
  747:     CREATE TABLE abc(a, b, c);
  748:     CREATE TABLE abc_mirror(a, b, c);
  749:     CREATE TEMP TRIGGER BEFORE INSERT ON abc BEGIN 
  750:       INSERT INTO abc_mirror(a, b, c) VALUES(new.a, new.b, new.c);
  751:     END;
  752:     INSERT INTO abc VALUES(1, 2, 3);
  753:     SELECT * FROM abc_mirror;
  754:   }
  755: } {1 2 3}
  756: do_test shared-$av.9.2 {
  757:   execsql {
  758:     INSERT INTO abc VALUES(4, 5, 6);
  759:     SELECT * FROM abc_mirror;
  760:   } db2
  761: } {1 2 3}
  762: do_test shared-$av.9.3 {
  763:   db close
  764:   db2 close
  765: } {}
  766: 
  767: } ; # End shared-9.*
  768: 
  769: #---------------------------------------------------------------------------
  770: # The following tests - shared-10.* - test that the library behaves 
  771: # correctly when a connection to a shared-cache is closed. 
  772: #
  773: do_test shared-$av.10.1 {
  774:   # Create a small sample database with two connections to it (db and db2).
  775:   forcedelete test.db
  776:   sqlite3 db  test.db
  777:   sqlite3 db2 test.db
  778:   execsql {
  779:     CREATE TABLE ab(a PRIMARY KEY, b);
  780:     CREATE TABLE de(d PRIMARY KEY, e);
  781:     INSERT INTO ab VALUES('Chiang Mai', 100000);
  782:     INSERT INTO ab VALUES('Bangkok', 8000000);
  783:     INSERT INTO de VALUES('Ubon', 120000);
  784:     INSERT INTO de VALUES('Khon Kaen', 200000);
  785:   }
  786: } {}
  787: do_test shared-$av.10.2 {
  788:   # Open a read-transaction with the first connection, a write-transaction
  789:   # with the second.
  790:   execsql {
  791:     BEGIN;
  792:     SELECT * FROM ab;
  793:   }
  794:   execsql {
  795:     BEGIN;
  796:     INSERT INTO de VALUES('Pataya', 30000);
  797:   } db2
  798: } {}
  799: do_test shared-$av.10.3 {
  800:   # An external connection should be able to read the database, but not
  801:   # prepare a write operation.
  802:   if {$::tcl_platform(platform)=="unix"} {
  803:     sqlite3 db3 ./test.db
  804:   } else {
  805:     sqlite3 db3 TEST.DB
  806:   }
  807:   execsql {
  808:     SELECT * FROM ab;
  809:   } db3
  810:   catchsql {
  811:     BEGIN;
  812:     INSERT INTO de VALUES('Pataya', 30000);
  813:   } db3
  814: } {1 {database is locked}}
  815: do_test shared-$av.10.4 {
  816:   # Close the connection with the write-transaction open
  817:   db2 close
  818: } {}
  819: do_test shared-$av.10.5 {
  820:   # Test that the db2 transaction has been automatically rolled back.
  821:   # If it has not the ('Pataya', 30000) entry will still be in the table.
  822:   execsql {
  823:     SELECT * FROM de;
  824:   }
  825: } {Ubon 120000 {Khon Kaen} 200000}
  826: do_test shared-$av.10.5 {
  827:   # Closing db2 should have dropped the shared-cache back to a read-lock.
  828:   # So db3 should be able to prepare a write...
  829:   catchsql {INSERT INTO de VALUES('Pataya', 30000);} db3
  830: } {0 {}}
  831: do_test shared-$av.10.6 {
  832:   # ... but not commit it.
  833:   catchsql {COMMIT} db3
  834: } {1 {database is locked}}
  835: do_test shared-$av.10.7 {
  836:   # Commit the (read-only) db transaction. Check via db3 to make sure the 
  837:   # contents of table "de" are still as they should be.
  838:   execsql {
  839:     COMMIT;
  840:   }
  841:   execsql {
  842:     SELECT * FROM de;
  843:   } db3
  844: } {Ubon 120000 {Khon Kaen} 200000 Pataya 30000}
  845: do_test shared-$av.10.9 {
  846:   # Commit the external transaction.
  847:   catchsql {COMMIT} db3
  848: } {0 {}}
  849: integrity_check shared-$av.10.10
  850: do_test shared-$av.10.11 {
  851:   db close
  852:   db3 close
  853: } {}
  854: 
  855: do_test shared-$av.11.1 {
  856:   forcedelete test.db
  857:   sqlite3 db  test.db
  858:   sqlite3 db2 test.db
  859:   execsql {
  860:     CREATE TABLE abc(a, b, c);
  861:     CREATE TABLE abc2(a, b, c);
  862:     BEGIN;
  863:     INSERT INTO abc VALUES(1, 2, 3);
  864:   }
  865: } {}
  866: do_test shared-$av.11.2 {
  867:   catchsql {BEGIN;} db2
  868:   catchsql {SELECT * FROM abc;} db2
  869: } {1 {database table is locked: abc}}
  870: do_test shared-$av.11.3 {
  871:   catchsql {BEGIN} db2
  872: } {1 {cannot start a transaction within a transaction}}
  873: do_test shared-$av.11.4 {
  874:   catchsql {SELECT * FROM abc2;} db2
  875: } {0 {}}
  876: do_test shared-$av.11.5 {
  877:   catchsql {INSERT INTO abc2 VALUES(1, 2, 3);} db2
  878: } {1 {database table is locked}}
  879: do_test shared-$av.11.6 {
  880:   catchsql {SELECT * FROM abc2}
  881: } {0 {}}
  882: do_test shared-$av.11.6 {
  883:   execsql {
  884:     ROLLBACK;
  885:     PRAGMA read_uncommitted = 1;
  886:   } db2
  887: } {}
  888: do_test shared-$av.11.7 {
  889:   execsql {
  890:     INSERT INTO abc2 VALUES(4, 5, 6);
  891:     INSERT INTO abc2 VALUES(7, 8, 9);
  892:   }
  893: } {}
  894: do_test shared-$av.11.8 {
  895:   set res [list]
  896:   db2 eval {
  897:     SELECT abc.a as I, abc2.a as II FROM abc, abc2;
  898:   } {
  899:     execsql {
  900:       DELETE FROM abc WHERE 1;
  901:     }
  902:     lappend res $I $II
  903:   }
  904:   set res
  905: } {1 4 {} 7}
  906: if {[llength [info command sqlite3_shared_cache_report]]==1} {
  907:   do_test shared-$av.11.9 {
  908:     string tolower [sqlite3_shared_cache_report]
  909:   } [string tolower [list [file nativename [file normalize test.db]] 2]]
  910: }
  911: 
  912: do_test shared-$av.11.11 {
  913:   db close
  914:   db2 close
  915: } {}
  916: 
  917: # This tests that if it is impossible to free any pages, SQLite will
  918: # exceed the limit set by PRAGMA cache_size.
  919: forcedelete test.db test.db-journal
  920: sqlite3 db test.db 
  921: ifcapable pager_pragmas {
  922:   do_test shared-$av.12.1 {
  923:     execsql {
  924:       PRAGMA cache_size = 10;
  925:       PRAGMA cache_size;
  926:     }
  927:   } {10}
  928: }
  929: do_test shared-$av.12.2 {
  930:   set ::db_handles [list]
  931:   for {set i 1} {$i < 15} {incr i} {
  932:     lappend ::db_handles db$i
  933:     sqlite3 db$i test.db 
  934:     execsql "CREATE TABLE db${i}(a, b, c)" db$i 
  935:     execsql "INSERT INTO db${i} VALUES(1, 2, 3)"
  936:   }
  937: } {}
  938: proc nested_select {handles} {
  939:   [lindex $handles 0] eval "SELECT * FROM [lindex $handles 0]" {
  940:     lappend ::res $a $b $c
  941:     if {[llength $handles]>1} {
  942:       nested_select [lrange $handles 1 end]
  943:     }
  944:   }
  945: }
  946: do_test shared-$av.12.3 {
  947:   set ::res [list]
  948:   nested_select $::db_handles
  949:   set ::res
  950: } [string range [string repeat "1 2 3 " [llength $::db_handles]] 0 end-1]
  951: 
  952: do_test shared-$av.12.X {
  953:   db close
  954:   foreach h $::db_handles { 
  955:     $h close
  956:   }
  957: } {}
  958: 
  959: # Internally, locks are acquired on shared B-Tree structures in the order
  960: # that the structures appear in the virtual memory address space. This
  961: # test case attempts to cause the order of the structures in memory 
  962: # to be different from the order in which they are attached to a given
  963: # database handle. This covers an extra line or two.
  964: #
  965: do_test shared-$av.13.1 {
  966:   forcedelete test2.db test3.db test4.db test5.db
  967:   sqlite3 db :memory:
  968:   execsql {
  969:     ATTACH 'test2.db' AS aux2;
  970:     ATTACH 'test3.db' AS aux3;
  971:     ATTACH 'test4.db' AS aux4;
  972:     ATTACH 'test5.db' AS aux5;
  973:     DETACH aux2;
  974:     DETACH aux3;
  975:     DETACH aux4;
  976:     ATTACH 'test2.db' AS aux2;
  977:     ATTACH 'test3.db' AS aux3;
  978:     ATTACH 'test4.db' AS aux4;
  979:   }
  980: } {}
  981: do_test shared-$av.13.2 {
  982:   execsql {
  983:     CREATE TABLE t1(a, b, c);
  984:     CREATE TABLE aux2.t2(a, b, c);
  985:     CREATE TABLE aux3.t3(a, b, c);
  986:     CREATE TABLE aux4.t4(a, b, c);
  987:     CREATE TABLE aux5.t5(a, b, c);
  988:     SELECT count(*) FROM 
  989:       aux2.sqlite_master, 
  990:       aux3.sqlite_master, 
  991:       aux4.sqlite_master, 
  992:       aux5.sqlite_master
  993:   }
  994: } {1}
  995: do_test shared-$av.13.3 {
  996:   db close
  997: } {}
  998: 
  999: # Test that nothing horrible happens if a connection to a shared B-Tree 
 1000: # structure is closed while some other connection has an open cursor.
 1001: #
 1002: do_test shared-$av.14.1 {
 1003:   sqlite3 db test.db
 1004:   sqlite3 db2 test.db
 1005:   execsql {SELECT name FROM sqlite_master}
 1006: } {db1 db2 db3 db4 db5 db6 db7 db8 db9 db10 db11 db12 db13 db14}
 1007: do_test shared-$av.14.2 {
 1008:   set res [list]
 1009:   db eval {SELECT name FROM sqlite_master} {
 1010:     if {$name eq "db7"} {
 1011:       db2 close
 1012:     }
 1013:     lappend res $name
 1014:   }
 1015:   set res
 1016: } {db1 db2 db3 db4 db5 db6 db7 db8 db9 db10 db11 db12 db13 db14}
 1017: do_test shared-$av.14.3 {
 1018:   db close
 1019: } {}
 1020: 
 1021: # Populate a database schema using connection [db]. Then drop it using
 1022: # [db2]. This is to try to find any points where shared-schema elements
 1023: # are allocated using the lookaside buffer of [db].
 1024: # 
 1025: # Mutexes are enabled for this test as that activates a couple of useful
 1026: # assert() statements in the C code.
 1027: #
 1028: do_test shared-$av-15.1 {
 1029:   forcedelete test.db
 1030:   sqlite3 db test.db -fullmutex 1
 1031:   sqlite3 db2 test.db -fullmutex 1
 1032:   execsql {
 1033:     CREATE TABLE t1(a, b, c);
 1034:     CREATE INDEX i1 ON t1(a, b);
 1035:     CREATE VIEW v1 AS SELECT * FROM t1; 
 1036:     CREATE VIEW v2 AS SELECT * FROM t1, v1 
 1037:                       WHERE t1.c=v1.c GROUP BY t1.a ORDER BY v1.b; 
 1038:     CREATE TRIGGER tr1 AFTER INSERT ON t1 
 1039:       WHEN new.a!=1
 1040:     BEGIN
 1041:       DELETE FROM t1 WHERE a=5;
 1042:       INSERT INTO t1 VALUES(1, 2, 3);
 1043:       UPDATE t1 SET c=c+1;
 1044:     END;
 1045: 
 1046:     INSERT INTO t1 VALUES(5, 6, 7);
 1047:     INSERT INTO t1 VALUES(8, 9, 10);
 1048:     INSERT INTO t1 VALUES(11, 12, 13);
 1049:     ANALYZE;
 1050:     SELECT * FROM t1;
 1051:   }
 1052: } {1 2 6 8 9 12 1 2 5 11 12 14 1 2 4}
 1053: do_test shared-$av-15.2 {
 1054:   execsql { DROP TABLE t1 } db2
 1055: } {}
 1056: db close
 1057: db2 close
 1058: 
 1059: }
 1060: 
 1061: sqlite3_enable_shared_cache $::enable_shared_cache
 1062: finish_test

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