Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | If a write statement fails with OE_Abort, but there is no statement journal, roll the entire transaction back instead. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | rollback-abort |
Files: | files | file ages | folders |
SHA3-256: |
75a8ed7a4227493c0d992ceeef6d631e |
User & Date: | dan 2019-01-26 18:10:05.415 |
Context
2019-01-26
| ||
19:09 | Fix a broken assert() in fts3. (check-in: b8dd2d67b5 user: dan tags: rollback-abort) | |
18:10 | If a write statement fails with OE_Abort, but there is no statement journal, roll the entire transaction back instead. (check-in: 75a8ed7a42 user: dan tags: rollback-abort) | |
17:47 | Fix "PRAGMA journal_mode" so that if it fails because there is a transaction open, it does not roll that transaction back. (check-in: 9f39cb5b81 user: dan tags: rollback-abort) | |
15:40 | Add the ".eqp trace" command to the CLI when using SQLITE_DEBUG, as a convenient shorthand for "PRAGMA vdbe_debug=ON" but with automatic indentation feature for program listings provided by the CLI. (check-in: 626502faa1 user: drh tags: trunk) | |
Changes
Changes to src/vdbe.c.
︙ | ︙ | |||
984 985 986 987 988 989 990 | */ case OP_Halt: { VdbeFrame *pFrame; int pcx; pcx = (int)(pOp - aOp); #ifdef SQLITE_DEBUG | | | 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 | */ case OP_Halt: { VdbeFrame *pFrame; int pcx; pcx = (int)(pOp - aOp); #ifdef SQLITE_DEBUG if( pOp->p2==OE_Abort && !pOp->p3 ){ sqlite3VdbeAssertAbortable(p); } #endif if( pOp->p1==SQLITE_OK && p->pFrame ){ /* Halt the sub-program. Return control to the parent frame. */ pFrame = p->pFrame; p->pFrame = pFrame->pParent; p->nFrame--; sqlite3VdbeSetChanges(db, p->nChange); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
632 633 634 635 636 637 638 | VdbeOpIter sIter; memset(&sIter, 0, sizeof(sIter)); sIter.v = v; while( (pOp = opIterNext(&sIter))!=0 ){ int opcode = pOp->opcode; if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename | | | 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | VdbeOpIter sIter; memset(&sIter, 0, sizeof(sIter)); sIter.v = v; while( (pOp = opIterNext(&sIter))!=0 ){ int opcode = pOp->opcode; if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename || opcode==OP_VDestroy || opcode==OP_Vacuum || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) ){ hasAbort = 1; break; } if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1; |
︙ | ︙ | |||
740 741 742 743 744 745 746 747 748 749 750 751 752 753 | break; } #ifndef SQLITE_OMIT_WAL case OP_Checkpoint: #endif case OP_Vacuum: case OP_JournalMode: { p->readOnly = 0; p->bIsReader = 1; break; } case OP_Next: case OP_SorterNext: { pOp->p4.xAdvance = sqlite3BtreeNext; | > > > > > > | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 | break; } #ifndef SQLITE_OMIT_WAL case OP_Checkpoint: #endif case OP_Vacuum: case OP_JournalMode: { /* Neither VACUUM or "PRAGMA journal_mode" statements generate an ** OP_Transaction opcode. So setting usesStmtJournal does not cause ** either statement to actually open a statement journal. However, ** it does prevent them from rolling back an entire transaction ** if they fail because there is already a transaction open. */ p->usesStmtJournal = 1; p->readOnly = 0; p->bIsReader = 1; break; } case OP_Next: case OP_SorterNext: { pOp->p4.xAdvance = sqlite3BtreeNext; |
︙ | ︙ | |||
2199 2200 2201 2202 2203 2204 2205 | n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ assert( x.nFree>=0 ); assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); | < > | 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 | n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ assert( x.nFree>=0 ); assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) ); p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort); resolveP2Values(p, &nArg); if( pParse->explain && nMem<10 ){ nMem = 10; } p->expired = 0; /* Memory for registers, parameters, cursor, etc, is allocated in one or two ** passes. On the first pass, we try to reuse unused memory at the |
︙ | ︙ | |||
2939 2940 2941 2942 2943 2944 2945 | sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; } db->nStatement = 0; }else if( eStatementOp==0 ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ eStatementOp = SAVEPOINT_RELEASE; | | > > | 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 | sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; } db->nStatement = 0; }else if( eStatementOp==0 ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ eStatementOp = SAVEPOINT_RELEASE; }else if( p->errorAction==OE_Abort && (p->usesStmtJournal || p->readOnly || p->rc!=SQLITE_ERROR) ){ eStatementOp = SAVEPOINT_ROLLBACK; }else{ sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); sqlite3CloseSavepoints(db); db->autoCommit = 1; p->nChange = 0; } |
︙ | ︙ |
Changes to src/window.c.
︙ | ︙ | |||
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 | VdbeCoverageIf(v, eCond==1); VdbeCoverageIf(v, eCond==2); sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); VdbeCoverageNeverNullIf(v, eCond==0); VdbeCoverageNeverNullIf(v, eCond==1); VdbeCoverageNeverNullIf(v, eCond==2); sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC); sqlite3ReleaseTempReg(pParse, regZero); } /* ** Return the number of arguments passed to the window-function associated ** with the object passed as the only argument to this function. | > > > | 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 | VdbeCoverageIf(v, eCond==1); VdbeCoverageIf(v, eCond==2); sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg); VdbeCoverageNeverNullIf(v, eCond==0); VdbeCoverageNeverNullIf(v, eCond==1); VdbeCoverageNeverNullIf(v, eCond==2); sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort); #ifdef SQLITE_DEBUG sqlite3VdbeChangeP3(v, -1, 1); #endif sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC); sqlite3ReleaseTempReg(pParse, regZero); } /* ** Return the number of arguments passed to the window-function associated ** with the object passed as the only argument to this function. |
︙ | ︙ |
Changes to test/triggerG.test.
︙ | ︙ | |||
71 72 73 74 75 76 77 78 | END; } do_catchsql_test 310 { INSERT INTO t4 VALUES(1); } {1 {hex literal too big: 0x2147483648e0e0099}} finish_test | > > > > > > > > > > > > > > > > > > > > > | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | END; } do_catchsql_test 310 { INSERT INTO t4 VALUES(1); } {1 {hex literal too big: 0x2147483648e0e0099}} #------------------------------------------------------------------------- do_execsql_test 400 { CREATE TABLE x1(a, b); CREATE TRIGGER x1t AFTER INSERT ON x1 BEGIN SELECT abs(-9223372036854775808 + new.a); END; BEGIN; } do_catchsql_test 410 { INSERT INTO x1 VALUES(2, 2), (0, 0), (1, 1); } {1 {integer overflow}} do_execsql_test 420 { SELECT * FROM x1; } {} do_test 430 { sqlite3_get_autocommit db } {1} finish_test |
Changes to test/window1.test.
︙ | ︙ | |||
696 697 698 699 700 701 702 703 704 | WINDOW w1 AS (PARTITION BY b IN (SELECT rowid FROM t7)); } { 2 10 1 101 3 101 } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | WINDOW w1 AS (PARTITION BY b IN (SELECT rowid FROM t7)); } { 2 10 1 101 3 101 } #------------------------------------------------------------------------- do_execsql_test 17.0 { CREATE TABLE tbl1(a,b,c,d); CREATE TRIGGER r1 AFTER INSERT ON tbl1 WHEN new.a NOT NULL BEGIN SELECT sum(d) OVER (PARTITION BY b ORDER BY d ROWS BETWEEN 2 PRECEDING AND -2 FOLLOWING) FROM tbl1; END; } do_catchsql_test 17.1.1 { INSERT INTO tbl1(a) VALUES(1); } {1 {frame ending offset must be a non-negative integer}} do_execsql_test 17.1.2 { SELECT count(*) FROM tbl1; } 0 do_catchsql_test 17.2.1 { INSERT INTO tbl1(a) VALUES(NULL), (NULL), (1); } {1 {frame ending offset must be a non-negative integer}} do_execsql_test 17.2.2 { SELECT count(*) FROM tbl1; } 0 do_catchsql_test 17.3.1 { BEGIN; INSERT INTO tbl1(a) VALUES(NULL); INSERT INTO tbl1(a) VALUES(NULL), (1); } {1 {frame ending offset must be a non-negative integer}} do_execsql_test 17.3.2 { SELECT count(*) FROM tbl1; } 0 do_test 17.3.3 { sqlite3_get_autocommit db } 1 finish_test |