Annotation of embedaddon/sqlite3/test/savepoint.test, revision 1.1.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>