/ Check-in [75a8ed7a]
Login

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 | SQL archive
Timelines: family | ancestors | descendants | both | rollback-abort
Files: files | file ages | folders
SHA3-256:75a8ed7a4227493c0d992ceeef6d631ef9c3643fef380fc2c467916d8761551f
User & Date: dan 2019-01-26 18:10:05
Context
2019-01-26
19:09
Fix a broken assert() in fts3. check-in: b8dd2d67 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: 75a8ed7a 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: 9f39cb5b 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: 626502fa user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

   984    984   */
   985    985   case OP_Halt: {
   986    986     VdbeFrame *pFrame;
   987    987     int pcx;
   988    988   
   989    989     pcx = (int)(pOp - aOp);
   990    990   #ifdef SQLITE_DEBUG
   991         -  if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
          991  +  if( pOp->p2==OE_Abort && !pOp->p3 ){ sqlite3VdbeAssertAbortable(p); }
   992    992   #endif
   993    993     if( pOp->p1==SQLITE_OK && p->pFrame ){
   994    994       /* Halt the sub-program. Return control to the parent frame. */
   995    995       pFrame = p->pFrame;
   996    996       p->pFrame = pFrame->pParent;
   997    997       p->nFrame--;
   998    998       sqlite3VdbeSetChanges(db, p->nChange);

Changes to src/vdbeaux.c.

   632    632     VdbeOpIter sIter;
   633    633     memset(&sIter, 0, sizeof(sIter));
   634    634     sIter.v = v;
   635    635   
   636    636     while( (pOp = opIterNext(&sIter))!=0 ){
   637    637       int opcode = pOp->opcode;
   638    638       if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
   639         -     || opcode==OP_VDestroy
          639  +     || opcode==OP_VDestroy || opcode==OP_Vacuum
   640    640        || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
   641    641         && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
   642    642       ){
   643    643         hasAbort = 1;
   644    644         break;
   645    645       }
   646    646       if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;
................................................................................
   740    740             break;
   741    741           }
   742    742   #ifndef SQLITE_OMIT_WAL
   743    743           case OP_Checkpoint:
   744    744   #endif
   745    745           case OP_Vacuum:
   746    746           case OP_JournalMode: {
          747  +          /* Neither VACUUM or "PRAGMA journal_mode" statements generate an
          748  +          ** OP_Transaction opcode. So setting usesStmtJournal does not cause
          749  +          ** either statement to actually open a statement journal. However,
          750  +          ** it does prevent them from rolling back an entire transaction
          751  +          ** if they fail because there is already a transaction open.  */
          752  +          p->usesStmtJournal = 1;
   747    753             p->readOnly = 0;
   748    754             p->bIsReader = 1;
   749    755             break;
   750    756           }
   751    757           case OP_Next:
   752    758           case OP_SorterNext: {
   753    759             pOp->p4.xAdvance = sqlite3BtreeNext;
................................................................................
  2199   2205     n = ROUND8(sizeof(Op)*p->nOp);              /* Bytes of opcode memory used */
  2200   2206     x.pSpace = &((u8*)p->aOp)[n];               /* Unused opcode memory */
  2201   2207     assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
  2202   2208     x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n);  /* Bytes of unused memory */
  2203   2209     assert( x.nFree>=0 );
  2204   2210     assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
  2205   2211   
  2206         -  resolveP2Values(p, &nArg);
  2207   2212     p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
         2213  +  resolveP2Values(p, &nArg);
  2208   2214     if( pParse->explain && nMem<10 ){
  2209   2215       nMem = 10;
  2210   2216     }
  2211   2217     p->expired = 0;
  2212   2218   
  2213   2219     /* Memory for registers, parameters, cursor, etc, is allocated in one or two
  2214   2220     ** passes.  On the first pass, we try to reuse unused memory at the 
................................................................................
  2939   2945           sqlite3RollbackAll(db, SQLITE_OK);
  2940   2946           p->nChange = 0;
  2941   2947         }
  2942   2948         db->nStatement = 0;
  2943   2949       }else if( eStatementOp==0 ){
  2944   2950         if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){
  2945   2951           eStatementOp = SAVEPOINT_RELEASE;
  2946         -      }else if( p->errorAction==OE_Abort ){
         2952  +      }else if( p->errorAction==OE_Abort 
         2953  +           && (p->usesStmtJournal || p->readOnly || p->rc!=SQLITE_ERROR) 
         2954  +      ){
  2947   2955           eStatementOp = SAVEPOINT_ROLLBACK;
  2948   2956         }else{
  2949   2957           sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
  2950   2958           sqlite3CloseSavepoints(db);
  2951   2959           db->autoCommit = 1;
  2952   2960           p->nChange = 0;
  2953   2961         }

Changes to src/window.c.

  1072   1072     VdbeCoverageIf(v, eCond==1);
  1073   1073     VdbeCoverageIf(v, eCond==2);
  1074   1074     sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
  1075   1075     VdbeCoverageNeverNullIf(v, eCond==0);
  1076   1076     VdbeCoverageNeverNullIf(v, eCond==1);
  1077   1077     VdbeCoverageNeverNullIf(v, eCond==2);
  1078   1078     sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
         1079  +#ifdef SQLITE_DEBUG
         1080  +  sqlite3VdbeChangeP3(v, -1, 1);
         1081  +#endif
  1079   1082     sqlite3VdbeAppendP4(v, (void*)azErr[eCond], P4_STATIC);
  1080   1083     sqlite3ReleaseTempReg(pParse, regZero);
  1081   1084   }
  1082   1085   
  1083   1086   /*
  1084   1087   ** Return the number of arguments passed to the window-function associated
  1085   1088   ** with the object passed as the only argument to this function.

Changes to test/triggerG.test.

    71     71     END;
    72     72   }
    73     73   
    74     74   do_catchsql_test 310 {
    75     75     INSERT INTO t4 VALUES(1);
    76     76   } {1 {hex literal too big: 0x2147483648e0e0099}}
    77     77   
           78  +#-------------------------------------------------------------------------
           79  +
           80  +do_execsql_test 400 {
           81  +  CREATE TABLE x1(a, b);
           82  +  CREATE TRIGGER x1t AFTER INSERT ON x1 BEGIN
           83  +    SELECT abs(-9223372036854775808 + new.a);
           84  +  END;
           85  +  BEGIN;
           86  +}
           87  +
           88  +do_catchsql_test 410 {
           89  +  INSERT INTO x1 VALUES(2, 2), (0, 0), (1, 1);
           90  +} {1 {integer overflow}}
           91  +
           92  +do_execsql_test  420 {
           93  +  SELECT * FROM x1; 
           94  +} {}
           95  +
           96  +do_test  430 { sqlite3_get_autocommit db } {1}
           97  +
    78     98   finish_test
           99  +

Changes to test/window1.test.

   696    696     WINDOW w1 AS (PARTITION BY b IN (SELECT rowid FROM t7));
   697    697   } {
   698    698     2 10
   699    699     1 101
   700    700     3 101
   701    701   }
   702    702   
          703  +#-------------------------------------------------------------------------
          704  +do_execsql_test 17.0 {
          705  +  CREATE TABLE tbl1(a,b,c,d);
          706  +  CREATE TRIGGER r1 AFTER INSERT ON tbl1 WHEN new.a NOT NULL BEGIN
          707  +    SELECT sum(d) OVER
          708  +    (PARTITION BY b ORDER BY d ROWS BETWEEN 2 PRECEDING AND -2 FOLLOWING)
          709  +    FROM tbl1;
          710  +  END;
          711  +}
          712  +
          713  +do_catchsql_test 17.1.1 {
          714  +  INSERT INTO tbl1(a) VALUES(1);
          715  +} {1 {frame ending offset must be a non-negative integer}}
          716  +do_execsql_test 17.1.2 {
          717  +  SELECT count(*) FROM tbl1;
          718  +} 0
          719  +
          720  +do_catchsql_test 17.2.1 {
          721  +  INSERT INTO tbl1(a) VALUES(NULL), (NULL), (1);
          722  +} {1 {frame ending offset must be a non-negative integer}}
          723  +do_execsql_test 17.2.2 {
          724  +  SELECT count(*) FROM tbl1;
          725  +} 0
          726  +
          727  +do_catchsql_test 17.3.1 {
          728  +  BEGIN;
          729  +    INSERT INTO tbl1(a) VALUES(NULL);
          730  +    INSERT INTO tbl1(a) VALUES(NULL), (1);
          731  +} {1 {frame ending offset must be a non-negative integer}}
          732  +do_execsql_test 17.3.2 {
          733  +  SELECT count(*) FROM tbl1;
          734  +} 0
          735  +do_test 17.3.3 { sqlite3_get_autocommit db } 1
   703    736   
   704    737   finish_test