Annotation of embedaddon/sqlite3/test/savepoint.test, revision 1.1

1.1     ! misho       1: # 2008 December 15
        !             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: savepoint.test,v 1.13 2009/07/18 08:30:45 danielk1977 Exp $
        !            13: 
        !            14: set testdir [file dirname $argv0]
        !            15: source $testdir/tester.tcl
        !            16: source $testdir/lock_common.tcl
        !            17: source $testdir/malloc_common.tcl
        !            18: 
        !            19: #----------------------------------------------------------------------
        !            20: # The following tests - savepoint-1.* - test that the SAVEPOINT, RELEASE
        !            21: # and ROLLBACK TO comands are correctly parsed, and that the auto-commit
        !            22: # flag is correctly set and unset as a result.
        !            23: #
        !            24: do_test savepoint-1.1 {
        !            25:   wal_set_journal_mode
        !            26:   execsql {
        !            27:     SAVEPOINT sp1;
        !            28:     RELEASE sp1;
        !            29:   }
        !            30: } {}
        !            31: do_test savepoint-1.2 {
        !            32:   execsql {
        !            33:     SAVEPOINT sp1;
        !            34:     ROLLBACK TO sp1;
        !            35:   }
        !            36: } {}
        !            37: do_test savepoint-1.3 {
        !            38:   execsql { SAVEPOINT sp1 }
        !            39:   db close
        !            40: } {}
        !            41: sqlite3 db test.db
        !            42: do_test savepoint-1.4.1 {
        !            43:   execsql {
        !            44:     SAVEPOINT sp1;
        !            45:     SAVEPOINT sp2;
        !            46:     RELEASE sp1;
        !            47:   }
        !            48:   sqlite3_get_autocommit db
        !            49: } {1}
        !            50: do_test savepoint-1.4.2 {
        !            51:   execsql {
        !            52:     SAVEPOINT sp1;
        !            53:     SAVEPOINT sp2;
        !            54:     RELEASE sp2;
        !            55:   }
        !            56:   sqlite3_get_autocommit db
        !            57: } {0}
        !            58: do_test savepoint-1.4.3 {
        !            59:   execsql { RELEASE sp1 }
        !            60:   sqlite3_get_autocommit db
        !            61: } {1}
        !            62: do_test savepoint-1.4.4 {
        !            63:   execsql {
        !            64:     SAVEPOINT sp1;
        !            65:     SAVEPOINT sp2;
        !            66:     ROLLBACK TO sp1;
        !            67:   }
        !            68:   sqlite3_get_autocommit db
        !            69: } {0}
        !            70: do_test savepoint-1.4.5 {
        !            71:   execsql { RELEASE SAVEPOINT sp1 }
        !            72:   sqlite3_get_autocommit db
        !            73: } {1}
        !            74: do_test savepoint-1.4.6 {
        !            75:   execsql {
        !            76:     SAVEPOINT sp1;
        !            77:     SAVEPOINT sp2;
        !            78:     SAVEPOINT sp3;
        !            79:     ROLLBACK TO SAVEPOINT sp3;
        !            80:     ROLLBACK TRANSACTION TO sp2;
        !            81:     ROLLBACK TRANSACTION TO SAVEPOINT sp1;
        !            82:   }
        !            83:   sqlite3_get_autocommit db
        !            84: } {0}
        !            85: do_test savepoint-1.4.7 {
        !            86:   execsql { RELEASE SAVEPOINT SP1 }
        !            87:   sqlite3_get_autocommit db
        !            88: } {1}
        !            89: do_test savepoint-1.5 {
        !            90:   execsql {
        !            91:     SAVEPOINT sp1;
        !            92:     ROLLBACK TO sp1;
        !            93:   }
        !            94: } {}
        !            95: do_test savepoint-1.6 {
        !            96:   execsql COMMIT
        !            97: } {}
        !            98: wal_check_journal_mode savepoint-1.7
        !            99: 
        !           100: #------------------------------------------------------------------------
        !           101: # These tests - savepoint-2.* - test rollbacks and releases of savepoints
        !           102: # with a very simple data set.
        !           103: # 
        !           104: 
        !           105: do_test savepoint-2.1 {
        !           106:   execsql {
        !           107:     CREATE TABLE t1(a, b, c);
        !           108:     BEGIN;
        !           109:     INSERT INTO t1 VALUES(1, 2, 3);
        !           110:     SAVEPOINT one;
        !           111:     UPDATE t1 SET a = 2, b = 3, c = 4;
        !           112:   }
        !           113:   execsql { SELECT * FROM t1 }
        !           114: } {2 3 4}
        !           115: do_test savepoint-2.2 {
        !           116:   execsql {
        !           117:     ROLLBACK TO one;
        !           118:   }
        !           119:   execsql { SELECT * FROM t1 }
        !           120: } {1 2 3}
        !           121: do_test savepoint-2.3 {
        !           122:   execsql {
        !           123:     INSERT INTO t1 VALUES(4, 5, 6);
        !           124:   }
        !           125:   execsql { SELECT * FROM t1 }
        !           126: } {1 2 3 4 5 6}
        !           127: do_test savepoint-2.4 {
        !           128:   execsql {
        !           129:     ROLLBACK TO one;
        !           130:   }
        !           131:   execsql { SELECT * FROM t1 }
        !           132: } {1 2 3}
        !           133: 
        !           134: 
        !           135: do_test savepoint-2.5 {
        !           136:   execsql {
        !           137:     INSERT INTO t1 VALUES(7, 8, 9);
        !           138:     SAVEPOINT two;
        !           139:     INSERT INTO t1 VALUES(10, 11, 12);
        !           140:   }
        !           141:   execsql { SELECT * FROM t1 }
        !           142: } {1 2 3 7 8 9 10 11 12}
        !           143: do_test savepoint-2.6 {
        !           144:   execsql {
        !           145:     ROLLBACK TO two;
        !           146:   }
        !           147:   execsql { SELECT * FROM t1 }
        !           148: } {1 2 3 7 8 9}
        !           149: do_test savepoint-2.7 {
        !           150:   execsql {
        !           151:     INSERT INTO t1 VALUES(10, 11, 12);
        !           152:   }
        !           153:   execsql { SELECT * FROM t1 }
        !           154: } {1 2 3 7 8 9 10 11 12}
        !           155: do_test savepoint-2.8 {
        !           156:   execsql {
        !           157:     ROLLBACK TO one;
        !           158:   }
        !           159:   execsql { SELECT * FROM t1 }
        !           160: } {1 2 3}
        !           161: do_test savepoint-2.9 {
        !           162:   execsql {
        !           163:     INSERT INTO t1 VALUES('a', 'b', 'c');
        !           164:     SAVEPOINT two;
        !           165:     INSERT INTO t1 VALUES('d', 'e', 'f');
        !           166:   }
        !           167:   execsql { SELECT * FROM t1 }
        !           168: } {1 2 3 a b c d e f}
        !           169: do_test savepoint-2.10 {
        !           170:   execsql {
        !           171:     RELEASE two;
        !           172:   }
        !           173:   execsql { SELECT * FROM t1 }
        !           174: } {1 2 3 a b c d e f}
        !           175: do_test savepoint-2.11 {
        !           176:   execsql {
        !           177:     ROLLBACK;
        !           178:   }
        !           179:   execsql { SELECT * FROM t1 }
        !           180: } {}
        !           181: wal_check_journal_mode savepoint-2.12
        !           182: 
        !           183: #------------------------------------------------------------------------
        !           184: # This block of tests - savepoint-3.* - test that when a transaction
        !           185: # savepoint is rolled back, locks are not released from database files.
        !           186: # And that when a transaction savepoint is released, they are released.
        !           187: #
        !           188: # These tests do not work in WAL mode. WAL mode does not take RESERVED
        !           189: # locks on the database file.
        !           190: # 
        !           191: if {[wal_is_wal_mode]==0} {
        !           192:   do_test savepoint-3.1 {
        !           193:     execsql { SAVEPOINT "transaction" }
        !           194:     execsql { PRAGMA lock_status }
        !           195:   } {main unlocked temp closed}
        !           196:   
        !           197:   do_test savepoint-3.2 {
        !           198:     execsql { INSERT INTO t1 VALUES(1, 2, 3) }
        !           199:     execsql { PRAGMA lock_status }
        !           200:   } {main reserved temp closed}
        !           201:   
        !           202:   do_test savepoint-3.3 {
        !           203:     execsql { ROLLBACK TO "transaction" }
        !           204:     execsql { PRAGMA lock_status }
        !           205:   } {main reserved temp closed}
        !           206:   
        !           207:   do_test savepoint-3.4 {
        !           208:     execsql { INSERT INTO t1 VALUES(1, 2, 3) }
        !           209:     execsql { PRAGMA lock_status }
        !           210:   } {main reserved temp closed}
        !           211:   
        !           212:   do_test savepoint-3.5 {
        !           213:     execsql { RELEASE "transaction" }
        !           214:     execsql { PRAGMA lock_status }
        !           215:   } {main unlocked temp closed}
        !           216: }
        !           217: 
        !           218: #------------------------------------------------------------------------
        !           219: # Test that savepoints that include schema modifications are handled
        !           220: # correctly. Test cases savepoint-4.*.
        !           221: # 
        !           222: do_test savepoint-4.1 {
        !           223:   execsql {
        !           224:     CREATE TABLE t2(d, e, f);
        !           225:     SELECT sql FROM sqlite_master;
        !           226:   }
        !           227: } {{CREATE TABLE t1(a, b, c)} {CREATE TABLE t2(d, e, f)}}
        !           228: do_test savepoint-4.2 {
        !           229:   execsql {
        !           230:     BEGIN;
        !           231:     CREATE TABLE t3(g,h);
        !           232:     INSERT INTO t3 VALUES('I', 'II');
        !           233:     SAVEPOINT one;
        !           234:     DROP TABLE t3;
        !           235:   }
        !           236: } {}
        !           237: do_test savepoint-4.3 {
        !           238:   execsql {
        !           239:     CREATE TABLE t3(g, h, i);
        !           240:     INSERT INTO t3 VALUES('III', 'IV', 'V');
        !           241:   }
        !           242:   execsql {SELECT * FROM t3}
        !           243: } {III IV V}
        !           244: do_test savepoint-4.4 {
        !           245:   execsql { ROLLBACK TO one; }
        !           246:   execsql {SELECT * FROM t3}
        !           247: } {I II}
        !           248: do_test savepoint-4.5 {
        !           249:   execsql {
        !           250:     ROLLBACK;
        !           251:     SELECT sql FROM sqlite_master;
        !           252:   }
        !           253: } {{CREATE TABLE t1(a, b, c)} {CREATE TABLE t2(d, e, f)}}
        !           254: 
        !           255: do_test savepoint-4.6 {
        !           256:   execsql {
        !           257:     BEGIN;
        !           258:     INSERT INTO t1 VALUES('o', 't', 't');
        !           259:     SAVEPOINT sp1;
        !           260:     CREATE TABLE t3(a, b, c);
        !           261:     INSERT INTO t3 VALUES('z', 'y', 'x');
        !           262:   }
        !           263:   execsql {SELECT * FROM t3}
        !           264: } {z y x}
        !           265: do_test savepoint-4.7 {
        !           266:   execsql {
        !           267:     ROLLBACK TO sp1;
        !           268:     CREATE TABLE t3(a);
        !           269:     INSERT INTO t3 VALUES('value');
        !           270:   }
        !           271:   execsql {SELECT * FROM t3}
        !           272: } {value}
        !           273: do_test savepoint-4.8 {
        !           274:   execsql COMMIT
        !           275: } {}
        !           276: wal_check_journal_mode savepoint-4.9
        !           277: 
        !           278: #------------------------------------------------------------------------
        !           279: # Test some logic errors to do with the savepoint feature.
        !           280: # 
        !           281: 
        !           282: ifcapable incrblob {
        !           283:   do_test savepoint-5.1.1 {
        !           284:     execsql {
        !           285:       CREATE TABLE blobs(x);
        !           286:       INSERT INTO blobs VALUES('a twentyeight character blob');
        !           287:     }
        !           288:     set fd [db incrblob blobs x 1]
        !           289:     puts -nonewline $fd "hello"
        !           290:     catchsql {SAVEPOINT abc}
        !           291:   } {1 {cannot open savepoint - SQL statements in progress}}
        !           292:   do_test savepoint-5.1.2 {
        !           293:     close $fd
        !           294:     catchsql {SAVEPOINT abc}
        !           295:   } {0 {}}
        !           296:   
        !           297:   do_test savepoint-5.2 {
        !           298:     execsql  {RELEASE abc}
        !           299:     catchsql {RELEASE abc}
        !           300:   } {1 {no such savepoint: abc}}
        !           301:   
        !           302:   do_test savepoint-5.3.1 {
        !           303:     execsql  {SAVEPOINT abc}
        !           304:     catchsql {ROLLBACK TO def}
        !           305:   } {1 {no such savepoint: def}}
        !           306:   do_test savepoint-5.3.2 {
        !           307:     execsql  {SAVEPOINT def}
        !           308:     set fd [db incrblob -readonly blobs x 1]
        !           309:     catchsql {ROLLBACK TO def}
        !           310:   } {1 {cannot rollback savepoint - SQL statements in progress}}
        !           311:   do_test savepoint-5.3.3 {
        !           312:     catchsql  {RELEASE def}
        !           313:   } {0 {}}
        !           314:   do_test savepoint-5.3.4 {
        !           315:     close $fd
        !           316:     execsql  {savepoint def}
        !           317:     set fd [db incrblob blobs x 1]
        !           318:     catchsql {release def}
        !           319:   } {1 {cannot release savepoint - SQL statements in progress}}
        !           320:   do_test savepoint-5.3.5 {
        !           321:     close $fd
        !           322:     execsql {release abc}
        !           323:   } {}
        !           324:   
        !           325:   # Rollback mode:
        !           326:   #
        !           327:   #   Open a savepoint transaction and insert a row into the database. Then,
        !           328:   #   using a second database handle, open a read-only transaction on the
        !           329:   #   database file. Check that the savepoint transaction cannot be committed
        !           330:   #   until after the read-only transaction has been closed.
        !           331:   #
        !           332:   # WAL mode:
        !           333:   # 
        !           334:   #   As above, except that the savepoint transaction can be successfully
        !           335:   #   committed before the read-only transaction has been closed.
        !           336:   #
        !           337:   do_test savepoint-5.4.1 {
        !           338:     execsql {
        !           339:       SAVEPOINT main;
        !           340:       INSERT INTO blobs VALUES('another blob');
        !           341:     }
        !           342:   } {}
        !           343:   do_test savepoint-5.4.2 {
        !           344:     sqlite3 db2 test.db
        !           345:     execsql { BEGIN ; SELECT count(*) FROM blobs } db2
        !           346:   } {1}
        !           347:   if {[wal_is_wal_mode]} {
        !           348:     do_test savepoint-5.4.3 { catchsql "RELEASE main" } {0 {}}
        !           349:     do_test savepoint-5.4.4 { db2 close               } {}
        !           350:   } else {
        !           351:     do_test savepoint-5.4.3 {
        !           352:       catchsql { RELEASE main }
        !           353:     } {1 {database is locked}}
        !           354:     do_test savepoint-5.4.4 {
        !           355:       db2 close
        !           356:       catchsql { RELEASE main }
        !           357:     } {0 {}}
        !           358:   }
        !           359:   do_test savepoint-5.4.5 {
        !           360:     execsql { SELECT x FROM blobs WHERE rowid = 2 }
        !           361:   } {{another blob}}
        !           362:   do_test savepoint-5.4.6 {
        !           363:     execsql { SELECT count(*) FROM blobs }
        !           364:   } {2}
        !           365: }
        !           366: wal_check_journal_mode savepoint-5.5
        !           367: 
        !           368: #-------------------------------------------------------------------------
        !           369: # The following tests, savepoint-6.*, test an incr-vacuum inside of a
        !           370: # couple of nested savepoints.
        !           371: #
        !           372: ifcapable {autovacuum && pragma} {
        !           373:   db close
        !           374:   forcedelete test.db
        !           375:   sqlite3 db test.db
        !           376: 
        !           377:   do_test savepoint-6.1 {
        !           378:     execsql { PRAGMA auto_vacuum = incremental }
        !           379:     wal_set_journal_mode
        !           380:     execsql {
        !           381:       CREATE TABLE t1(a, b, c);
        !           382:       CREATE INDEX i1 ON t1(a, b);
        !           383:       BEGIN;
        !           384:       INSERT INTO t1 VALUES(randstr(10,400),randstr(10,400),randstr(10,400));
        !           385:     }
        !           386:     set r "randstr(10,400)"
        !           387:     for {set ii 0} {$ii < 10} {incr ii} {
        !           388:       execsql "INSERT INTO t1 SELECT $r, $r, $r FROM t1"
        !           389:     }
        !           390:     execsql { COMMIT }
        !           391:   } {}
        !           392: 
        !           393:   integrity_check savepoint-6.2
        !           394: 
        !           395:   do_test savepoint-6.3 {
        !           396:     execsql {
        !           397:       PRAGMA cache_size = 10;
        !           398:       BEGIN;
        !           399:         UPDATE t1 SET a = randstr(10,10) WHERE (rowid%4)==0;
        !           400:         SAVEPOINT one;
        !           401:           DELETE FROM t1 WHERE rowid%2;
        !           402:           PRAGMA incr_vacuum;
        !           403:           SAVEPOINT two;
        !           404:             INSERT INTO t1 SELECT randstr(10,400), randstr(10,400), c FROM t1;
        !           405:             DELETE FROM t1 WHERE rowid%2;
        !           406:             PRAGMA incr_vacuum;
        !           407:         ROLLBACK TO one;
        !           408:       COMMIT;
        !           409:     }
        !           410:   } {}
        !           411: 
        !           412:   integrity_check savepoint-6.4
        !           413: 
        !           414:   wal_check_journal_mode savepoint-6.5
        !           415: }
        !           416: 
        !           417: #-------------------------------------------------------------------------
        !           418: # The following tests, savepoint-7.*, attempt to break the logic 
        !           419: # surrounding savepoints by growing and shrinking the database file.
        !           420: #
        !           421: db close
        !           422: forcedelete test.db
        !           423: sqlite3 db test.db
        !           424: 
        !           425: do_test savepoint-7.1 {
        !           426:   execsql { PRAGMA auto_vacuum = incremental }
        !           427:   wal_set_journal_mode
        !           428:   execsql {
        !           429:     PRAGMA cache_size = 10;
        !           430:     BEGIN;
        !           431:     CREATE TABLE t1(a PRIMARY KEY, b);
        !           432:       INSERT INTO t1(a) VALUES('alligator');
        !           433:       INSERT INTO t1(a) VALUES('angelfish');
        !           434:       INSERT INTO t1(a) VALUES('ant');
        !           435:       INSERT INTO t1(a) VALUES('antelope');
        !           436:       INSERT INTO t1(a) VALUES('ape');
        !           437:       INSERT INTO t1(a) VALUES('baboon');
        !           438:       INSERT INTO t1(a) VALUES('badger');
        !           439:       INSERT INTO t1(a) VALUES('bear');
        !           440:       INSERT INTO t1(a) VALUES('beetle');
        !           441:       INSERT INTO t1(a) VALUES('bird');
        !           442:       INSERT INTO t1(a) VALUES('bison');
        !           443:       UPDATE t1 SET b =    randstr(1000,1000);
        !           444:       UPDATE t1 SET b = b||randstr(1000,1000);
        !           445:       UPDATE t1 SET b = b||randstr(1000,1000);
        !           446:       UPDATE t1 SET b = b||randstr(10,1000);
        !           447:     COMMIT;
        !           448:   }
        !           449:   expr ([execsql { PRAGMA page_count }] > 20)
        !           450: } {1}
        !           451: do_test savepoint-7.2.1 {
        !           452:   execsql {
        !           453:     BEGIN;
        !           454:       SAVEPOINT one;
        !           455:       CREATE TABLE t2(a, b);
        !           456:       INSERT INTO t2 SELECT a, b FROM t1;
        !           457:       ROLLBACK TO one;
        !           458:   }
        !           459:   execsql {
        !           460:     PRAGMA integrity_check;
        !           461:   }
        !           462: } {ok}
        !           463: do_test savepoint-7.2.2 {
        !           464:   execsql {
        !           465:     COMMIT;
        !           466:     PRAGMA integrity_check;
        !           467:   }
        !           468: } {ok}
        !           469: 
        !           470: do_test savepoint-7.3.1 {
        !           471:   execsql {
        !           472:     CREATE TABLE t2(a, b);
        !           473:     INSERT INTO t2 SELECT a, b FROM t1;
        !           474:   }
        !           475: } {}
        !           476: do_test savepoint-7.3.2 {
        !           477:   execsql {
        !           478:     BEGIN;
        !           479:       SAVEPOINT one;
        !           480:         DELETE FROM t2;
        !           481:         PRAGMA incremental_vacuum;
        !           482:         SAVEPOINT two;
        !           483:           INSERT INTO t2 SELECT a, b FROM t1;
        !           484:         ROLLBACK TO two;
        !           485:     COMMIT;
        !           486:   }
        !           487:   execsql { PRAGMA integrity_check }
        !           488: } {ok}
        !           489: wal_check_journal_mode savepoint-7.3.3
        !           490: 
        !           491: do_test savepoint-7.4.1 {
        !           492:   db close
        !           493:   forcedelete test.db
        !           494:   sqlite3 db test.db
        !           495:   execsql { PRAGMA auto_vacuum = incremental }
        !           496:   wal_set_journal_mode
        !           497:   execsql {
        !           498:     CREATE TABLE t1(a, b, PRIMARY KEY(a, b));
        !           499:     INSERT INTO t1 VALUES(randstr(1000,1000), randstr(1000,1000));
        !           500:     BEGIN;
        !           501:       DELETE FROM t1;
        !           502:       SAVEPOINT one;
        !           503:       PRAGMA incremental_vacuum;
        !           504:       ROLLBACK TO one;
        !           505:     COMMIT;
        !           506:   }
        !           507: 
        !           508:   execsql { PRAGMA integrity_check }
        !           509: } {ok}
        !           510: 
        !           511: do_test savepoint-7.5.1 {
        !           512:   execsql {
        !           513:     PRAGMA incremental_vacuum;
        !           514:     CREATE TABLE t5(x, y);
        !           515:     INSERT INTO t5 VALUES(1, randstr(1000,1000));
        !           516:     INSERT INTO t5 VALUES(2, randstr(1000,1000));
        !           517:     INSERT INTO t5 VALUES(3, randstr(1000,1000));
        !           518: 
        !           519:     BEGIN;
        !           520:       INSERT INTO t5 VALUES(4, randstr(1000,1000));
        !           521:       INSERT INTO t5 VALUES(5, randstr(1000,1000));
        !           522:       DELETE FROM t5 WHERE x=1 OR x=2;
        !           523:       SAVEPOINT one;
        !           524:         PRAGMA incremental_vacuum;
        !           525:         SAVEPOINT two;
        !           526:           INSERT INTO t5 VALUES(1, randstr(1000,1000));
        !           527:           INSERT INTO t5 VALUES(2, randstr(1000,1000));
        !           528:         ROLLBACK TO two;
        !           529:       ROLLBACK TO one;
        !           530:     COMMIT;
        !           531:     PRAGMA integrity_check;
        !           532:   }
        !           533: } {ok}
        !           534: do_test savepoint-7.5.2 {
        !           535:   execsql {
        !           536:     DROP TABLE t5;
        !           537:   }
        !           538: } {}
        !           539: wal_check_journal_mode savepoint-7.5.3
        !           540: 
        !           541: # Test oddly named and quoted savepoints.
        !           542: #
        !           543: do_test savepoint-8-1 {
        !           544:   execsql { SAVEPOINT "save1" }
        !           545:   execsql { RELEASE save1 }
        !           546: } {}
        !           547: do_test savepoint-8-2 {
        !           548:   execsql { SAVEPOINT "Including whitespace " }
        !           549:   execsql { RELEASE "including Whitespace " }
        !           550: } {}
        !           551: 
        !           552: # Test that the authorization callback works.
        !           553: #
        !           554: ifcapable auth {
        !           555:   proc auth {args} {
        !           556:     eval lappend ::authdata $args
        !           557:     return SQLITE_OK
        !           558:   }
        !           559:   db auth auth
        !           560: 
        !           561:   do_test savepoint-9.1 {
        !           562:     set ::authdata [list]
        !           563:     execsql { SAVEPOINT sp1 }
        !           564:     set ::authdata
        !           565:   } {SQLITE_SAVEPOINT BEGIN sp1 {} {}}
        !           566:   do_test savepoint-9.2 {
        !           567:     set ::authdata [list]
        !           568:     execsql { ROLLBACK TO sp1 }
        !           569:     set ::authdata
        !           570:   } {SQLITE_SAVEPOINT ROLLBACK sp1 {} {}}
        !           571:   do_test savepoint-9.3 {
        !           572:     set ::authdata [list]
        !           573:     execsql { RELEASE sp1 }
        !           574:     set ::authdata
        !           575:   } {SQLITE_SAVEPOINT RELEASE sp1 {} {}}
        !           576: 
        !           577:   proc auth {args} {
        !           578:     eval lappend ::authdata $args
        !           579:     return SQLITE_DENY
        !           580:   }
        !           581:   db auth auth
        !           582: 
        !           583:   do_test savepoint-9.4 {
        !           584:     set ::authdata [list]
        !           585:     set res [catchsql { SAVEPOINT sp1 }]
        !           586:     concat $::authdata $res
        !           587:   } {SQLITE_SAVEPOINT BEGIN sp1 {} {} 1 {not authorized}}
        !           588:   do_test savepoint-9.5 {
        !           589:     set ::authdata [list]
        !           590:     set res [catchsql { ROLLBACK TO sp1 }]
        !           591:     concat $::authdata $res
        !           592:   } {SQLITE_SAVEPOINT ROLLBACK sp1 {} {} 1 {not authorized}}
        !           593:   do_test savepoint-9.6 {
        !           594:     set ::authdata [list]
        !           595:     set res [catchsql { RELEASE sp1 }]
        !           596:     concat $::authdata $res
        !           597:   } {SQLITE_SAVEPOINT RELEASE sp1 {} {} 1 {not authorized}}
        !           598: 
        !           599:   catch { db eval ROLLBACK }
        !           600:   db auth ""
        !           601: }
        !           602: 
        !           603: #-------------------------------------------------------------------------
        !           604: # The following tests - savepoint-10.* - test the interaction of 
        !           605: # savepoints and ATTACH statements.
        !           606: # 
        !           607: 
        !           608: # First make sure it is not possible to attach or detach a database while
        !           609: # a savepoint is open (it is not possible if any transaction is open).
        !           610: #
        !           611: do_test savepoint-10.1.1 {
        !           612:   catchsql {
        !           613:     SAVEPOINT one;
        !           614:     ATTACH 'test2.db' AS aux;
        !           615:   }
        !           616: } {1 {cannot ATTACH database within transaction}}
        !           617: do_test savepoint-10.1.2 {
        !           618:   execsql {
        !           619:     RELEASE one;
        !           620:     ATTACH 'test2.db' AS aux;
        !           621:   }
        !           622:   catchsql {
        !           623:     SAVEPOINT one;
        !           624:     DETACH aux;
        !           625:   }
        !           626: } {1 {cannot DETACH database within transaction}}
        !           627: do_test savepoint-10.1.3 {
        !           628:   execsql {
        !           629:     RELEASE one;
        !           630:     DETACH aux;
        !           631:   }
        !           632: } {}
        !           633: 
        !           634: # The lock state of the TEMP database can vary if SQLITE_TEMP_STORE=3
        !           635: # And the following set of tests is only really interested in the status
        !           636: # of the aux1 and aux2 locks.  So record the current lock status of
        !           637: # TEMP for use in the answers.
        !           638: set templockstate [lindex [db eval {PRAGMA lock_status}] 3]
        !           639: 
        !           640: 
        !           641: if {[wal_is_wal_mode]==0} {
        !           642:   do_test savepoint-10.2.1 {
        !           643:     forcedelete test3.db
        !           644:     forcedelete test2.db
        !           645:     execsql {
        !           646:       ATTACH 'test2.db' AS aux1;
        !           647:       ATTACH 'test3.db' AS aux2;
        !           648:       DROP TABLE t1;
        !           649:       CREATE TABLE main.t1(x, y);
        !           650:       CREATE TABLE aux1.t2(x, y);
        !           651:       CREATE TABLE aux2.t3(x, y);
        !           652:       SELECT name FROM sqlite_master 
        !           653:         UNION ALL
        !           654:       SELECT name FROM aux1.sqlite_master 
        !           655:         UNION ALL
        !           656:       SELECT name FROM aux2.sqlite_master;
        !           657:     }
        !           658:   } {t1 t2 t3}
        !           659:   do_test savepoint-10.2.2 {
        !           660:     execsql { PRAGMA lock_status }
        !           661:   } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked]
        !           662:   
        !           663:   do_test savepoint-10.2.3 {
        !           664:     execsql {
        !           665:       SAVEPOINT one;
        !           666:       INSERT INTO t1 VALUES(1, 2);
        !           667:       PRAGMA lock_status;
        !           668:     }
        !           669:   } [list main reserved temp $templockstate aux1 unlocked aux2 unlocked]
        !           670:   do_test savepoint-10.2.4 {
        !           671:     execsql {
        !           672:       INSERT INTO t3 VALUES(3, 4);
        !           673:       PRAGMA lock_status;
        !           674:     }
        !           675:   } [list main reserved temp $templockstate aux1 unlocked aux2 reserved]
        !           676:   do_test savepoint-10.2.5 {
        !           677:     execsql {
        !           678:       SAVEPOINT two;
        !           679:       INSERT INTO t2 VALUES(5, 6);
        !           680:       PRAGMA lock_status;
        !           681:     }
        !           682:   } [list main reserved temp $templockstate aux1 reserved aux2 reserved]
        !           683:   do_test savepoint-10.2.6 {
        !           684:     execsql { SELECT * FROM t2 }
        !           685:   } {5 6}
        !           686:   do_test savepoint-10.2.7 {
        !           687:     execsql { ROLLBACK TO two }
        !           688:     execsql { SELECT * FROM t2 }
        !           689:   } {}
        !           690:   do_test savepoint-10.2.8 {
        !           691:     execsql { PRAGMA lock_status }
        !           692:   } [list main reserved temp $templockstate aux1 reserved aux2 reserved]
        !           693:   do_test savepoint-10.2.9 {
        !           694:     execsql { SELECT 'a', * FROM t1 UNION ALL SELECT 'b', * FROM t3 }
        !           695:   } {a 1 2 b 3 4}
        !           696:   do_test savepoint-10.2.9 {
        !           697:     execsql {
        !           698:       INSERT INTO t2 VALUES(5, 6);
        !           699:       RELEASE one;
        !           700:     }
        !           701:     execsql { 
        !           702:       SELECT * FROM t1;
        !           703:       SELECT * FROM t2;
        !           704:       SELECT * FROM t3;
        !           705:     }
        !           706:   } {1 2 5 6 3 4}
        !           707:   do_test savepoint-10.2.9 {
        !           708:     execsql { PRAGMA lock_status }
        !           709:   } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked]
        !           710:   
        !           711:   do_test savepoint-10.2.10 {
        !           712:     execsql { 
        !           713:       SAVEPOINT one;
        !           714:         INSERT INTO t1 VALUES('a', 'b');
        !           715:         SAVEPOINT two;
        !           716:           INSERT INTO t2 VALUES('c', 'd');
        !           717:           SAVEPOINT three;
        !           718:             INSERT INTO t3 VALUES('e', 'f');
        !           719:     }
        !           720:     execsql { 
        !           721:       SELECT * FROM t1;
        !           722:       SELECT * FROM t2;
        !           723:       SELECT * FROM t3;
        !           724:     }
        !           725:   } {1 2 a b 5 6 c d 3 4 e f}
        !           726:   do_test savepoint-10.2.11 {
        !           727:     execsql { ROLLBACK TO two }
        !           728:     execsql { 
        !           729:       SELECT * FROM t1;
        !           730:       SELECT * FROM t2;
        !           731:       SELECT * FROM t3;
        !           732:     }
        !           733:   } {1 2 a b 5 6 3 4}
        !           734:   do_test savepoint-10.2.12 {
        !           735:     execsql { 
        !           736:       INSERT INTO t3 VALUES('g', 'h');
        !           737:       ROLLBACK TO two;
        !           738:     }
        !           739:     execsql { 
        !           740:       SELECT * FROM t1;
        !           741:       SELECT * FROM t2;
        !           742:       SELECT * FROM t3;
        !           743:     }
        !           744:   } {1 2 a b 5 6 3 4}
        !           745:   do_test savepoint-10.2.13 {
        !           746:     execsql { ROLLBACK }
        !           747:     execsql { 
        !           748:       SELECT * FROM t1;
        !           749:       SELECT * FROM t2;
        !           750:       SELECT * FROM t3;
        !           751:     }
        !           752:   } {1 2 5 6 3 4}
        !           753:   do_test savepoint-10.2.14 {
        !           754:     execsql { PRAGMA lock_status }
        !           755:   } [list main unlocked temp $templockstate aux1 unlocked aux2 unlocked]
        !           756: }
        !           757: 
        !           758: #-------------------------------------------------------------------------
        !           759: # The following tests - savepoint-11.* - test the interaction of 
        !           760: # savepoints and creating or dropping tables and indexes in 
        !           761: # auto-vacuum mode.
        !           762: # 
        !           763: do_test savepoint-11.1 {
        !           764:   db close
        !           765:   forcedelete test.db
        !           766:   sqlite3 db test.db
        !           767:   execsql { PRAGMA auto_vacuum = full; }
        !           768:   wal_set_journal_mode
        !           769:   execsql {
        !           770:     CREATE TABLE t1(a, b, UNIQUE(a, b));
        !           771:     INSERT INTO t1 VALUES(1, randstr(1000,1000));
        !           772:     INSERT INTO t1 VALUES(2, randstr(1000,1000));
        !           773:   }
        !           774: } {}
        !           775: do_test savepoint-11.2 {
        !           776:   execsql {
        !           777:     SAVEPOINT one;
        !           778:       CREATE TABLE t2(a, b, UNIQUE(a, b));
        !           779:       SAVEPOINT two;
        !           780:         CREATE TABLE t3(a, b, UNIQUE(a, b));
        !           781:   }
        !           782: } {}
        !           783: integrity_check savepoint-11.3
        !           784: do_test savepoint-11.4 {
        !           785:   execsql { ROLLBACK TO two }
        !           786: } {}
        !           787: integrity_check savepoint-11.5
        !           788: do_test savepoint-11.6 {
        !           789:   execsql { 
        !           790:     CREATE TABLE t3(a, b, UNIQUE(a, b));
        !           791:     ROLLBACK TO one;
        !           792:   }
        !           793: } {}
        !           794: integrity_check savepoint-11.7
        !           795: do_test savepoint-11.8 {
        !           796:   execsql { ROLLBACK }
        !           797:   execsql { PRAGMA wal_checkpoint }
        !           798:   file size test.db
        !           799: } {8192}
        !           800: 
        !           801: do_test savepoint-11.9 {
        !           802:   execsql {
        !           803:     DROP TABLE IF EXISTS t1;
        !           804:     DROP TABLE IF EXISTS t2;
        !           805:     DROP TABLE IF EXISTS t3;
        !           806:   }
        !           807: } {}
        !           808: do_test savepoint-11.10 {
        !           809:   execsql {
        !           810:     BEGIN;
        !           811:       CREATE TABLE t1(a, b);
        !           812:       CREATE TABLE t2(x, y);
        !           813:       INSERT INTO t2 VALUES(1, 2);
        !           814:       SAVEPOINT one;
        !           815:         INSERT INTO t2 VALUES(3, 4);
        !           816:         SAVEPOINT two;
        !           817:           DROP TABLE t1;
        !           818:         ROLLBACK TO two;
        !           819:   }
        !           820:   execsql {SELECT * FROM t2}
        !           821: } {1 2 3 4}
        !           822: do_test savepoint-11.11 {
        !           823:   execsql COMMIT
        !           824: } {}
        !           825: do_test savepoint-11.12 {
        !           826:   execsql {SELECT * FROM t2}
        !           827: } {1 2 3 4}
        !           828: wal_check_journal_mode savepoint-11.13
        !           829: 
        !           830: #-------------------------------------------------------------------------
        !           831: # The following tests - savepoint-12.* - test the interaction of 
        !           832: # savepoints and "ON CONFLICT ROLLBACK" clauses.
        !           833: # 
        !           834: do_test savepoint-12.1 {
        !           835:   execsql {
        !           836:     CREATE TABLE t4(a PRIMARY KEY, b);
        !           837:     INSERT INTO t4 VALUES(1, 'one');
        !           838:   }
        !           839: } {}
        !           840: do_test savepoint-12.2 {
        !           841:   # The final statement of the following SQL hits a constraint when the
        !           842:   # conflict handling mode is "OR ROLLBACK" and there are a couple of
        !           843:   # open savepoints. At one point this would fail to clear the internal
        !           844:   # record of the open savepoints, resulting in an assert() failure 
        !           845:   # later on.
        !           846:   # 
        !           847:   catchsql {
        !           848:     BEGIN;
        !           849:       INSERT INTO t4 VALUES(2, 'two');
        !           850:       SAVEPOINT sp1;
        !           851:         INSERT INTO t4 VALUES(3, 'three');
        !           852:         SAVEPOINT sp2;
        !           853:           INSERT OR ROLLBACK INTO t4 VALUES(1, 'one');
        !           854:   }
        !           855: } {1 {column a is not unique}}
        !           856: do_test savepoint-12.3 {
        !           857:   sqlite3_get_autocommit db
        !           858: } {1}
        !           859: do_test savepoint-12.4 {
        !           860:   execsql { SAVEPOINT one }
        !           861: } {}
        !           862: wal_check_journal_mode savepoint-12.5
        !           863: 
        !           864: #-------------------------------------------------------------------------
        !           865: # The following tests - savepoint-13.* - test the interaction of 
        !           866: # savepoints and "journal_mode = off".
        !           867: # 
        !           868: if {[wal_is_wal_mode]==0} {
        !           869:   do_test savepoint-13.1 {
        !           870:     db close
        !           871:     catch {forcedelete test.db}
        !           872:     sqlite3 db test.db
        !           873:     execsql {
        !           874:       BEGIN;
        !           875:         CREATE TABLE t1(a PRIMARY KEY, b);
        !           876:         INSERT INTO t1 VALUES(1, 2);
        !           877:       COMMIT;
        !           878:       PRAGMA journal_mode = off;
        !           879:     }
        !           880:   } {off}
        !           881:   do_test savepoint-13.2 {
        !           882:     execsql {
        !           883:       BEGIN;
        !           884:       INSERT INTO t1 VALUES(3, 4);
        !           885:       INSERT INTO t1 SELECT a+4,b+4  FROM t1;
        !           886:       COMMIT;
        !           887:     }
        !           888:   } {}
        !           889:   do_test savepoint-13.3 {
        !           890:     execsql {
        !           891:       BEGIN;
        !           892:         INSERT INTO t1 VALUES(9, 10);
        !           893:         SAVEPOINT s1;
        !           894:           INSERT INTO t1 VALUES(11, 12);
        !           895:       COMMIT;
        !           896:     }
        !           897:   } {}
        !           898:   do_test savepoint-13.4 {
        !           899:     execsql {
        !           900:       BEGIN;
        !           901:         INSERT INTO t1 VALUES(13, 14);
        !           902:         SAVEPOINT s1;
        !           903:           INSERT INTO t1 VALUES(15, 16);
        !           904:         ROLLBACK TO s1;
        !           905:       ROLLBACK;
        !           906:       SELECT * FROM t1;
        !           907:     }
        !           908:   } {1 2 3 4 5 6 7 8 9 10 11 12}
        !           909: }
        !           910: 
        !           911: db close
        !           912: delete_file test.db
        !           913: do_multiclient_test tn {
        !           914:   do_test savepoint-14.$tn.1 {
        !           915:     sql1 {
        !           916:       CREATE TABLE foo(x);
        !           917:       INSERT INTO foo VALUES(1);
        !           918:       INSERT INTO foo VALUES(2);
        !           919:     }
        !           920:     sql2 {
        !           921:       BEGIN;
        !           922:         SELECT * FROM foo;
        !           923:     }
        !           924:   } {1 2}
        !           925:   do_test savepoint-14.$tn.2 {
        !           926:     sql1 {
        !           927:       SAVEPOINT one;
        !           928:       INSERT INTO foo VALUES(1);
        !           929:     }
        !           930:     csql1 { RELEASE one }
        !           931:   } {1 {database is locked}}
        !           932:   do_test savepoint-14.$tn.3 {
        !           933:     sql1 { ROLLBACK TO one }
        !           934:     sql2 { COMMIT }
        !           935:     sql1 { RELEASE one }
        !           936:   } {}
        !           937: 
        !           938:   do_test savepoint-14.$tn.4 {
        !           939:     sql2 {
        !           940:       BEGIN;
        !           941:         SELECT * FROM foo;
        !           942:     }
        !           943:   } {1 2}
        !           944:   do_test savepoint-14.$tn.5 {
        !           945:     sql1 {
        !           946:       SAVEPOINT one;
        !           947:       INSERT INTO foo VALUES(1);
        !           948:     }
        !           949:     csql1 { RELEASE one }
        !           950:   } {1 {database is locked}}
        !           951:   do_test savepoint-14.$tn.6 {
        !           952:     sql2 { COMMIT }
        !           953:     sql1 {
        !           954:       ROLLBACK TO one;
        !           955:       INSERT INTO foo VALUES(3);
        !           956:       INSERT INTO foo VALUES(4);
        !           957:       INSERT INTO foo VALUES(5);
        !           958:       RELEASE one;
        !           959:     }
        !           960:   } {}
        !           961:   do_test savepoint-14.$tn.7 {
        !           962:     sql2 { CREATE INDEX fooidx ON foo(x); }
        !           963:     sql3 { PRAGMA integrity_check }
        !           964:   } {ok}
        !           965: }
        !           966: 
        !           967: do_multiclient_test tn {
        !           968:   do_test savepoint-15.$tn.1 {
        !           969:     sql1 {
        !           970:       CREATE TABLE foo(x);
        !           971:       INSERT INTO foo VALUES(1);
        !           972:       INSERT INTO foo VALUES(2);
        !           973:     }
        !           974:     sql2 { BEGIN; SELECT * FROM foo; }
        !           975:   } {1 2}
        !           976:   do_test savepoint-15.$tn.2 {
        !           977:     sql1 {
        !           978:       PRAGMA locking_mode = EXCLUSIVE;
        !           979:       BEGIN;
        !           980:         INSERT INTO foo VALUES(3);
        !           981:     }
        !           982:     csql1 { COMMIT }
        !           983:   } {1 {database is locked}}
        !           984:   do_test savepoint-15.$tn.3 {
        !           985:     sql1 { ROLLBACK }
        !           986:     sql2 { COMMIT }
        !           987:     sql1 {
        !           988:       INSERT INTO foo VALUES(3);
        !           989:       PRAGMA locking_mode = NORMAL;
        !           990:       INSERT INTO foo VALUES(4);
        !           991:     }
        !           992:     sql2 { CREATE INDEX fooidx ON foo(x); }
        !           993:     sql3 { PRAGMA integrity_check }
        !           994:   } {ok}
        !           995: }
        !           996: 
        !           997: do_multiclient_test tn {
        !           998:   do_test savepoint-16.$tn.1 {
        !           999:     sql1 {
        !          1000:       CREATE TABLE foo(x);
        !          1001:       INSERT INTO foo VALUES(1);
        !          1002:       INSERT INTO foo VALUES(2);
        !          1003:     }
        !          1004:   } {}
        !          1005:   do_test savepoint-16.$tn.2 {
        !          1006: 
        !          1007:     db eval {SELECT * FROM foo} {
        !          1008:       sql1 { INSERT INTO foo VALUES(3) }
        !          1009:       sql2 { SELECT * FROM foo }
        !          1010:       sql1 { INSERT INTO foo VALUES(4) }
        !          1011:       break
        !          1012:     }
        !          1013: 
        !          1014:     sql2 { CREATE INDEX fooidx ON foo(x); }
        !          1015:     sql3 { PRAGMA integrity_check }
        !          1016:   } {ok}
        !          1017:   do_test savepoint-16.$tn.3 {
        !          1018:     sql1 { SELECT * FROM foo }
        !          1019:   } {1 2 3 4}
        !          1020: }
        !          1021: 
        !          1022: #-------------------------------------------------------------------------
        !          1023: # This next block of tests verifies that a problem reported on the mailing
        !          1024: # list has been resolved. At one point the second "CREATE TABLE t6" would
        !          1025: # fail as table t6 still existed in the internal cache of the db schema
        !          1026: # (even though it had been removed from the database by the ROLLBACK 
        !          1027: # command).
        !          1028: #
        !          1029: sqlite3 db test.db
        !          1030: do_execsql_test savepoint-17.1 {
        !          1031:   BEGIN;
        !          1032:     CREATE TABLE t6(a, b);
        !          1033:     INSERT INTO t6 VALUES(1, 2);
        !          1034:     SAVEPOINT one;
        !          1035:       INSERT INTO t6 VALUES(3, 4);
        !          1036:     ROLLBACK TO one;
        !          1037:     SELECT * FROM t6;
        !          1038:   ROLLBACK;
        !          1039: } {1 2}
        !          1040: 
        !          1041: do_execsql_test savepoint-17.2 {
        !          1042:   CREATE TABLE t6(a, b);
        !          1043: } {}
        !          1044: 
        !          1045: finish_test

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