/ Changes On Branch delete-without-rowid-opt
Login

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

Changes In Branch delete-without-rowid-opt Excluding Merge-Ins

This is equivalent to a diff from c5566bb39c to 70ec88b299

2015-09-29
12:19
Fix an off-by-one error in test function fts5_decode(). (check-in: 3a9f076250 user: dan tags: trunk)
11:59
Merge latest trunk change into this branch. (check-in: b519c0d67a user: dan tags: vtab-onepass)
2015-09-28
23:45
Avoid unnecessary cursors and seeking when running a DELETE against a WITHOUT ROWID table. (Leaf check-in: 70ec88b299 user: drh tags: delete-without-rowid-opt)
17:05
Extra information provided by .wheretrace on input flags to the query planner and on the result of sqlite3WhereOkOnePass(). (check-in: c5566bb39c user: drh tags: trunk)
15:08
Add test cases to the ONEPASS optimization corruption problem fixed by the previous check-in. (check-in: 5c14d44705 user: drh tags: trunk)

Changes to src/delete.c.

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
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







-
+
-
-
+












+
+







    }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
      /* For ONEPASS, no need to store the rowid/primary-key because rows
      ** one, so just keep it in its register(s) and fall through to the
      ** delete code.  */
      ** are deleted as they are discovered */
      nKey = nPk; /* OP_Found will use an unpacked key */
      aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
      if( aToOpen==0 ){
        sqlite3WhereEnd(pWInfo);
        goto delete_from_cleanup;
      }
      memset(aToOpen, 1, nIdx+1);
      aToOpen[nIdx+1] = 0;
      if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
      if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
      if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
    }else{
      /* For non-ONEPASS, remember the rowid/primary-key of the row to
      ** be deleted */
      if( pPk ){
        /* Add the PK key for this row to the temporary table */
        iKey = ++pParse->nMem;
        nKey = 0;   /* Zero tells OP_Found to use a composite key */
        sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
            sqlite3IndexAffinityStr(pParse->db, pPk), nPk);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey);
518
519
520
521
522
523
524



525
526
527
528
529
530
531
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535







+
+
+







      sqlite3VdbeChangeP5(v, OE_Abort);
      sqlite3MayAbort(pParse);
    }else
#endif
    {
      int count = (pParse->nested==0);    /* True to count changes */
      int iIdxNoSeek = -1;
      if( eOnePass!=ONEPASS_OFF ){
        sqlite3WhereHenceforthUseTableCursor(pWInfo, sqlite3VdbeCurrentAddr(v));
      }
      if( bComplex==0 && aiCurOnePass[1]!=iDataCur ){
        iIdxNoSeek = aiCurOnePass[1];
      }
      sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
          iKey, nKey, count, OE_Default, eOnePass, iIdxNoSeek);
    }
  

Changes to src/insert.c.

1676
1677
1678
1679
1680
1681
1682
1683
1684






1685
1686
1687
1688
1689
1690
1691
1676
1677
1678
1679
1680
1681
1682


1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695







-
-
+
+
+
+
+
+







  }else{
    sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName);
  }
  if( piIdxCur ) *piIdxCur = iBase;
  for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
    int iIdxCur = iBase++;
    assert( pIdx->pSchema==pTab->pSchema );
    if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){
      *piDataCur = iIdxCur;
    if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
      if( aToOpen && aToOpen[0]==0 ){
        iIdxCur = iDataCur;
        aToOpen[i+1] = 0;
      }
      if( piDataCur ) *piDataCur = iIdxCur;
    }
    if( aToOpen==0 || aToOpen[i+1] ){
      sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
      sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
      VdbeComment((v, "%s", pIdx->zName));
    }
  }

Changes to src/sqliteInt.h.

3370
3371
3372
3373
3374
3375
3376

3377
3378
3379
3380
3381
3382
3383
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384







+







#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
#endif
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
void sqlite3WhereEnd(WhereInfo*);
void sqlite3WhereHenceforthUseTableCursor(WhereInfo*,int addr);
u64 sqlite3WhereOutputRowCount(WhereInfo*);
int sqlite3WhereIsDistinct(WhereInfo*);
int sqlite3WhereIsOrdered(WhereInfo*);
int sqlite3WhereIsSorted(WhereInfo*);
int sqlite3WhereContinueLabel(WhereInfo*);
int sqlite3WhereBreakLabel(WhereInfo*);
int sqlite3WhereOkOnePass(WhereInfo*, int*);

Changes to src/where.c.

23
24
25
26
27
28
29












30
31
32
33
34
35
36
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48







+
+
+
+
+
+
+
+
+
+
+
+







static int whereLoopResize(sqlite3*, WhereLoop*, int);

/* Test variable that can be set to enable WHERE tracing */
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/***/ int sqlite3WhereTrace = 0;
#endif

/*
** When generating the end-of-WHERE-loop, do not transform references to
** the main table into references to the index after this address.
**
** This interface is invoked by DELETE at a point after when the
** table cursor is pointing to the correct address but before any
** of the index cursors have been deleted.
*/
void sqlite3WhereHenceforthUseTableCursor(WhereInfo *pWInfo, int addr){
  pWInfo->addrUseTabCur = addr;
}


/*
** Return the estimated number of output rows from a WHERE clause
*/
u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
  return sqlite3LogEstToInt(pWInfo->nRowOut);
}
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543



4544


4545
4546
4547
4548
4549
4550
4551
4546
4547
4548
4549
4550
4551
4552

4553
4554
4555
4556
4557

4558
4559
4560
4561
4562
4563
4564
4565
4566







-


+
+
+
-
+
+







    */
    if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
      pIdx = pLoop->u.btree.pIndex;
    }else if( pLoop->wsFlags & WHERE_MULTI_OR ){
      pIdx = pLevel->u.pCovidx;
    }
    if( pIdx
     && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable))
     && !db->mallocFailed
    ){
      if( pWInfo->addrUseTabCur ){
        last = pWInfo->addrUseTabCur;
      }else{
      last = sqlite3VdbeCurrentAddr(v);
        last = sqlite3VdbeCurrentAddr(v);
      }
      k = pLevel->addrBody;
      pOp = sqlite3VdbeGetOp(v, k);
      for(; k<last; k++, pOp++){
        if( pOp->p1!=pLevel->iTabCur ) continue;
        if( pOp->opcode==OP_Column ){
          int x = pOp->p2;
          assert( pIdx->pTable==pTab );

Changes to src/whereInt.h.

415
416
417
418
419
420
421

422
423
424
425
426
427
428
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429







+







  u8 eOnePass;              /* ONEPASS_OFF, or _SINGLE, or _MULTI */
  u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
  u8 eDistinct;             /* One of the WHERE_DISTINCT_* values below */
  u8 nLevel;                /* Number of nested loop */
  int iTop;                 /* The very beginning of the WHERE loop */
  int iContinue;            /* Jump here to continue with next record */
  int iBreak;               /* Jump here to break out of the loop */
  int addrUseTabCur;        /* Do not use index cursor after this address */
  int savedNQueryLoop;      /* pParse->nQueryLoop outside the WHERE loop */
  int aiCurOnePass[2];      /* OP_OpenWrite cursors for the ONEPASS opt */
  WhereMaskSet sMaskSet;    /* Map cursor numbers to bitmasks */
  WhereClause sWC;          /* Decomposition of the WHERE clause */
  WhereLevel a[1];          /* Information about each nest loop in WHERE */
};