/ Check-in [68cce272]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Enhancement the progress callback mechanism so that the progress callback is always invoked at least once at the end of a prepared statement if the opcode count has been exceeded. This makes the progress callback more effective at limiting run times. This check-in also includes and unrelated performance enhancement to OP_Column.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:68cce272e7f7cbc0c319ee8b7ff674d652cb1e95e903d99d848c41dff2b5d304
User & Date: drh 2019-02-12 21:04:33
Context
2019-02-12
22:58
Ensure that the nProgressLimit variable is always initialized in sqlite3VdbeExec(), even if the routine jumps to its exit processing early. check-in: 167b91df user: drh tags: trunk
21:04
Enhancement the progress callback mechanism so that the progress callback is always invoked at least once at the end of a prepared statement if the opcode count has been exceeded. This makes the progress callback more effective at limiting run times. This check-in also includes and unrelated performance enhancement to OP_Column. check-in: 68cce272 user: drh tags: trunk
16:58
Further performance improvements to btreeInitPage(). check-in: 93ae382e user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

   819    819     ** If the progress callback returns non-zero, exit the virtual machine with
   820    820     ** a return code SQLITE_ABORT.
   821    821     */
   822    822     if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
   823    823       assert( db->nProgressOps!=0 );
   824    824       nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
   825    825       if( db->xProgress(db->pProgressArg) ){
          826  +      nProgressLimit = 0xffffffff;
   826    827         rc = SQLITE_INTERRUPT;
   827    828         goto abort_due_to_error;
   828    829       }
   829    830     }
   830    831   #endif
   831    832     
   832    833     break;
................................................................................
  1364   1365   case OP_ResultRow: {
  1365   1366     Mem *pMem;
  1366   1367     int i;
  1367   1368     assert( p->nResColumn==pOp->p2 );
  1368   1369     assert( pOp->p1>0 );
  1369   1370     assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
  1370   1371   
  1371         -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  1372         -  /* Run the progress counter just before returning.
  1373         -  */
  1374         -  if( db->xProgress!=0
  1375         -   && nVmStep>=nProgressLimit 
  1376         -   && db->xProgress(db->pProgressArg)!=0
  1377         -  ){
  1378         -    rc = SQLITE_INTERRUPT;
  1379         -    goto abort_due_to_error;
  1380         -  }
  1381         -#endif
  1382         -
  1383   1372     /* If this statement has violated immediate foreign key constraints, do
  1384   1373     ** not return the number of rows modified. And do not RELEASE the statement
  1385   1374     ** transaction. It needs to be rolled back.  */
  1386   1375     if( SQLITE_OK!=(rc = sqlite3VdbeCheckFk(p, 0)) ){
  1387   1376       assert( db->flags&SQLITE_CountRows );
  1388   1377       assert( p->usesStmtJournal );
  1389   1378       goto abort_due_to_error;
................................................................................
  2602   2591       op_column_read_header:
  2603   2592         i = pC->nHdrParsed;
  2604   2593         offset64 = aOffset[i];
  2605   2594         zHdr = zData + pC->iHdrOffset;
  2606   2595         zEndHdr = zData + aOffset[0];
  2607   2596         testcase( zHdr>=zEndHdr );
  2608   2597         do{
  2609         -        if( (t = zHdr[0])<0x80 ){
         2598  +        if( (pC->aType[i] = t = zHdr[0])<0x80 ){
  2610   2599             zHdr++;
  2611   2600             offset64 += sqlite3VdbeOneByteSerialTypeLen(t);
  2612   2601           }else{
  2613   2602             zHdr += sqlite3GetVarint32(zHdr, &t);
         2603  +          pC->aType[i] = t;
  2614   2604             offset64 += sqlite3VdbeSerialTypeLen(t);
  2615   2605           }
  2616         -        pC->aType[i++] = t;
  2617         -        aOffset[i] = (u32)(offset64 & 0xffffffff);
         2606  +        aOffset[++i] = (u32)(offset64 & 0xffffffff);
  2618   2607         }while( i<=p2 && zHdr<zEndHdr );
  2619   2608   
  2620   2609         /* The record is corrupt if any of the following are true:
  2621   2610         ** (1) the bytes of the header extend past the declared header size
  2622   2611         ** (2) the entire header was used but not all data was used
  2623   2612         ** (3) the end of the data extends beyond the end of the record.
  2624   2613         */
................................................................................
  7591   7580       sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
  7592   7581     }
  7593   7582   
  7594   7583     /* This is the only way out of this procedure.  We have to
  7595   7584     ** release the mutexes on btrees that were acquired at the
  7596   7585     ** top. */
  7597   7586   vdbe_return:
  7598         -  testcase( nVmStep>0 );
         7587  +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
         7588  +  if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
         7589  +    if( db->xProgress(db->pProgressArg) ){
         7590  +      nProgressLimit = 0xffffffff;
         7591  +      rc = SQLITE_INTERRUPT;
         7592  +      goto abort_due_to_error;
         7593  +    }
         7594  +  }
         7595  +#endif
  7599   7596     p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
  7600   7597     sqlite3VdbeLeave(p);
  7601   7598     assert( rc!=SQLITE_OK || nExtraDelete==0 
  7602   7599          || sqlite3_strlike("DELETE%",p->zSql,0)!=0 
  7603   7600     );
  7604   7601     return rc;
  7605   7602