/ Check-in [f59a3326]
Login

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

Overview
Comment:Update some stale comments in delete.c. No changes to code.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | onepass-delete-or
Files: files | file ages | folders
SHA1: f59a33260cc853bb35f4259b05fd05bbbeb13945
User & Date: dan 2015-12-12 19:23:41
Context
2015-12-12
19:23
Update some stale comments in delete.c. No changes to code. Leaf check-in: f59a3326 user: dan tags: onepass-delete-or
17:31
Add further tests for the changes on this branch. Also fix a memory-leak that could follow a malloc failure. check-in: 21526012 user: dan tags: onepass-delete-or
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/delete.c.

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
...
415
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
...
442
443
444
445
446
447
448
449
450
451


452
453
454
455
456
457
458
...
486
487
488
489
490
491
492
493


494
495
496
497
498
499
500
  }else{
    iKey = pParse->nMem + 1;
    iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
    if( iKey>pParse->nMem ) pParse->nMem = iKey;
  }

  if( eOnePass!=ONEPASS_OFF ){
    /* For ONEPASS, no need to store the rowid/primary-key. There is only
    ** one, so just keep it in its register(s) and fall through to the
    ** delete code.  */
    nKey = nPk; /* OP_Found will use an unpacked key */
    aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
    if( aToOpen==0 ){
      sqlite3WhereEnd(pWInfo);
      return SQLITE_NOMEM;
    }
    memset(aToOpen, 1, nIdx+1);
................................................................................
    }else{
      /* Add the rowid of the row to be deleted to the RowSet */
      nKey = 1;  /* OP_Seek always uses a single rowid */
      sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
    }
  }

  /* If this DELETE cannot use the ONEPASS strategy, this is the 
  ** end of the WHERE loop */

  if( eOnePass!=ONEPASS_OFF ){
    addrBypass = sqlite3VdbeMakeLabel(v);
  }else{
    sqlite3WhereEnd(pWInfo);
  }

  /* Unless this is a view, open cursors for the table we are 
  ** deleting from and all its indices. If this is a view, then the
  ** only effect this statement has is to fire the INSTEAD OF 
  ** triggers.
  */
  if( !isView ){
    int iAddrOnce = 0;
    u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE);
    if( eOnePass==ONEPASS_MULTI ){
      iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
    }
    testcase( IsVirtual(pTab) );
................................................................................
    sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur, 
        aToOpen, &iDataCur, &iIdxCur);
    assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
    assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
    if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
  }

  /* Set up a loop over the rowids/primary-keys that were found in the
  ** where-clause loop above.
  */


  if( eOnePass!=ONEPASS_OFF ){
    assert( nKey==nPk );  /* OP_Found will use an unpacked key */
    if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
      assert( pPk!=0 || pTab->pSelect!=0 );
      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
      VdbeCoverage(v);
    }
................................................................................
    if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){
      iIdxNoSeek = aiCurOnePass[1];
    }
    sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
        iKey, nKey, count, OE_Default, eOnePass, iIdxNoSeek);
  }

  /* End of the loop over all rowids/primary-keys. */


  if( eOnePass!=ONEPASS_OFF ){
    sqlite3VdbeResolveLabel(v, addrBypass);
    sqlite3WhereEnd(pWInfo);
  }else if( pPk ){
    sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v);
    sqlite3VdbeJumpHere(v, addrLoop);
  }else{







|
|
|







 







|
|
>









|
<







 







|
|
|
>
>







 







|
>
>







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434

435
436
437
438
439
440
441
...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  }else{
    iKey = pParse->nMem + 1;
    iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
    if( iKey>pParse->nMem ) pParse->nMem = iKey;
  }

  if( eOnePass!=ONEPASS_OFF ){
    /* For a one-pass strategy, no need to store the rowid/primary-key in
    ** a RowSet or temporary table. It is read directly from its register(s) 
    ** by the delete code below. */
    nKey = nPk; /* OP_Found will use an unpacked key */
    aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
    if( aToOpen==0 ){
      sqlite3WhereEnd(pWInfo);
      return SQLITE_NOMEM;
    }
    memset(aToOpen, 1, nIdx+1);
................................................................................
    }else{
      /* Add the rowid of the row to be deleted to the RowSet */
      nKey = 1;  /* OP_Seek always uses a single rowid */
      sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
    }
  }

  /* If not using a one-pass strategy, this is the end of the first loop.
  ** A second loop, to iterate through the contents of the RowSet or
  ** temporary table populated above, is opened below. */
  if( eOnePass!=ONEPASS_OFF ){
    addrBypass = sqlite3VdbeMakeLabel(v);
  }else{
    sqlite3WhereEnd(pWInfo);
  }

  /* Unless this is a view, open cursors for the table we are 
  ** deleting from and all its indices. If this is a view, then the
  ** only effect this statement has is to fire the INSTEAD OF 
  ** triggers.  */

  if( !isView ){
    int iAddrOnce = 0;
    u8 p5 = (eOnePass==ONEPASS_OFF ? 0 : OPFLAG_FORDELETE);
    if( eOnePass==ONEPASS_MULTI ){
      iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
    }
    testcase( IsVirtual(pTab) );
................................................................................
    sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, p5, iTabCur, 
        aToOpen, &iDataCur, &iIdxCur);
    assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
    assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
    if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
  }

  /* If using a one-pass strategy, seek the data-cursor to the entry
  ** in the main table b-tree if where.c has not already done so.
  **
  ** If using the two-pass strategy, start a loop over the contents
  ** of the RowSet or temporary table populated by the first loop.  */
  if( eOnePass!=ONEPASS_OFF ){
    assert( nKey==nPk );  /* OP_Found will use an unpacked key */
    if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
      assert( pPk!=0 || pTab->pSelect!=0 );
      sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
      VdbeCoverage(v);
    }
................................................................................
    if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){
      iIdxNoSeek = aiCurOnePass[1];
    }
    sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
        iKey, nKey, count, OE_Default, eOnePass, iIdxNoSeek);
  }

  /* For a one-pass strategy, this is the end of the single loop. For a 
  ** two-pass strategy, the end of the loop over the rowids/primary-keys
  ** stored in the RowSet/temporary table.  */
  if( eOnePass!=ONEPASS_OFF ){
    sqlite3VdbeResolveLabel(v, addrBypass);
    sqlite3WhereEnd(pWInfo);
  }else if( pPk ){
    sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1); VdbeCoverage(v);
    sqlite3VdbeJumpHere(v, addrLoop);
  }else{