/ Check-in [9eafafa3]
Login

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

Overview
Comment:Basic DELETE operations now working on WITHOUT ROWID tables.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | omit-rowid
Files: files | file ages | folders
SHA1:9eafafa31c4a2bbcf48418743e0fcb17c374e9a6
User & Date: drh 2013-10-25 14:46:15
Context
2013-10-25
19:17
Progress toward getting UPDATE to work in WITHOUT ROWID tables. check-in: e557b7d8 user: drh tags: omit-rowid
14:46
Basic DELETE operations now working on WITHOUT ROWID tables. check-in: 9eafafa3 user: drh tags: omit-rowid
2013-10-24
19:48
Update the interface to the sqlite3GenerateRowDelete() utility so that it is able to handle WITHOUT ROWID tables. The implementation still needs to be completed. check-in: 85daf517 user: drh tags: omit-rowid
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/analyze.c.

   240    240         }
   241    241       }
   242    242     }
   243    243   
   244    244     /* Open the sqlite_stat[134] tables for writing. */
   245    245     for(i=0; aTable[i].zCols; i++){
   246    246       assert( i<ArraySize(aTable) );
   247         -    sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
   248         -    sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
          247  +    sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
   249    248       sqlite3VdbeChangeP5(v, aCreateTbl[i]);
   250    249     }
   251    250   }
   252    251   
   253    252   /*
   254    253   ** Recommended number of samples for sqlite_stat4
   255    254   */

Changes to src/build.c.

   638    638   /*
   639    639   ** Open the sqlite_master table stored in database number iDb for
   640    640   ** writing. The table is opened using cursor 0.
   641    641   */
   642    642   void sqlite3OpenMasterTable(Parse *p, int iDb){
   643    643     Vdbe *v = sqlite3GetVdbe(p);
   644    644     sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
   645         -  sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
   646         -  sqlite3VdbeChangeP4(v, -1, (char *)5, P4_INT32);  /* 5 column table */
          645  +  sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
   647    646     if( p->nTab==0 ){
   648    647       p->nTab = 1;
   649    648     }
   650    649   }
   651    650   
   652    651   /*
   653    652   ** Parameter zName points to a nul-terminated buffer containing the name

Changes to src/delete.c.

   348    348     ** this optimization caused the row change count (the value returned by 
   349    349     ** API function sqlite3_count_changes) to be set incorrectly.  */
   350    350     if( rcauth==SQLITE_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) 
   351    351      && 0==sqlite3FkRequired(pParse, pTab, 0, 0)
   352    352     ){
   353    353       assert( !isView );
   354    354       sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
   355         -    sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
   356         -                      pTab->zName, P4_STATIC);
          355  +    if( HasRowid(pTab) ){
          356  +      sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
          357  +                        pTab->zName, P4_STATIC);
          358  +    }
   357    359       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
   358    360         assert( pIdx->pSchema==pTab->pSchema );
   359    361         sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
   360    362       }
   361    363     }else
   362    364   #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
   363         -  /* The usual case: There is a WHERE clause so we have to scan through
   364         -  ** the table and pick which records to delete.
   365         -  */
   366         -  {
          365  +  if( !HasRowid(pTab) ){
          366  +    /* There is a WHERE clause on a WITHOUT ROWID table.  
          367  +    */
          368  +    Index *pPk;      /* The PRIMARY KEY index on the table */
          369  +    int iPk;         /* First of nPk memory cells holding PRIMARY KEY value */
          370  +    int iEph;        /* Ephemeral table holding all primary key values */
          371  +    int iKey;        /* Key value inserting into iEph */
          372  +    i16 nPk;         /* Number of components of the PRIMARY KEY */
          373  +
          374  +    pPk = sqlite3PrimaryKeyIndex(pTab);
          375  +    assert( pPk!=0 );
          376  +    nPk = pPk->nKeyCol;
          377  +    iPk = pParse->nMem+1;
          378  +    pParse->nMem += nPk;
          379  +    iKey = ++pParse->nMem;
          380  +    iEph = pParse->nTab++;
          381  +
          382  +    sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iEph, nPk, 0, 
          383  +                      (char*)sqlite3IndexKeyinfo(pParse, pPk),
          384  +                      P4_KEYINFO_HANDOFF);
          385  +    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, 0, 0);
          386  +    if( pWInfo==0 ) goto delete_from_cleanup;
          387  +    for(i=0; i<nPk; i++){
          388  +      sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, pPk->aiColumn[i], iPk+i);
          389  +    }
          390  +    sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
          391  +                      sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT);
          392  +    sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, iKey);
          393  +    sqlite3WhereEnd(pWInfo);
          394  +
          395  +    /* Open cursors for all indices of the table.
          396  +    */
          397  +    sqlite3OpenTableAndIndices(pParse, pTab, iCur, iCur, OP_OpenWrite);
          398  +
          399  +    /* Loop over the primary keys to be deleted. */
          400  +    addr = sqlite3VdbeAddOp1(v, OP_Rewind, iEph);
          401  +    sqlite3VdbeAddOp2(v, OP_RowKey, iEph, iPk);
          402  +
          403  +    /* Delete the row */
          404  +    sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iCur, iPk, 0,
          405  +                             1, OE_Default);
          406  +
          407  +    /* End of the delete loop */
          408  +    sqlite3VdbeAddOp2(v, OP_Next, iEph, addr+1);
          409  +    sqlite3VdbeJumpHere(v, addr);
          410  +
          411  +    /* Close the cursors open on the table and its indexes. */
          412  +    for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
          413  +      sqlite3VdbeAddOp2(v, OP_Close, pIdx==pPk ? iCur : iCur + i, pIdx->tnum);
          414  +    }
          415  +  }else{
          416  +    /* There is a WHERE clause on a rowid table.  Run a loop that extracts
          417  +    ** all rowids to be deleted into a RowSet.
          418  +    */
   367    419       int iRowSet = ++pParse->nMem;   /* Register for rowset of rows to delete */
   368    420       int iRowid = ++pParse->nMem;    /* Used for storing rowid values. */
   369    421       int regRowid;                   /* Actual register containing rowids */
   370    422   
   371    423       /* Collect rowids of every row to be deleted.
   372    424       */
   373    425       sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
................................................................................
   388    440       end = sqlite3VdbeMakeLabel(v);
   389    441   
   390    442       /* Unless this is a view, open cursors for the table we are 
   391    443       ** deleting from and all its indices. If this is a view, then the
   392    444       ** only effect this statement has is to fire the INSTEAD OF 
   393    445       ** triggers.  */
   394    446       if( !isView ){
   395         -      sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
          447  +      sqlite3OpenTableAndIndices(pParse, pTab, iCur, -1, OP_OpenWrite);
   396    448       }
   397    449   
   398    450       addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
   399    451   
   400    452       /* Delete the row */
   401    453   #ifndef SQLITE_OMIT_VIRTUALTABLE
   402    454       if( IsVirtual(pTab) ){
................................................................................
   471    523   **       to be deleted, must be opened as cursor number iCur (except for
   472    524   **       WITHOUT ROWID tables which do not have a main table).
   473    525   **
   474    526   **   2.  Read/write cursors for all indices of pTab must be open as
   475    527   **       cursor number iCur+i for the i-th index.
   476    528   **
   477    529   **   3.  The primary key for the row to be deleted must be stored in a
   478         -**       sequence of memory cells starting at iPk.  If nPk==0 then the
   479         -**       primary key is a rowid an uses just one memory cell.  If nPk>0
   480         -**       then a WITHOUT ROWID table is being used and there are nPk elements
   481         -**       of the primary key.
          530  +**       sequence of memory cells starting at iPk. 
   482    531   **
   483    532   ** This routine generates code to remove both the table record and all 
   484    533   ** index entries that point to that record.
   485    534   */
   486    535   void sqlite3GenerateRowDelete(
   487    536     Parse *pParse,     /* Parsing context */
   488    537     Table *pTab,       /* Table containing the row to be deleted */
................................................................................
   492    541     i16 nPk,           /* Number of PRIMARY KEY memory cells */
   493    542     u8 count,          /* If non-zero, increment the row change counter */
   494    543     u8 onconf          /* Default ON CONFLICT policy for triggers */
   495    544   ){
   496    545     Vdbe *v = pParse->pVdbe;        /* Vdbe */
   497    546     int iOld = 0;                   /* First register in OLD.* array */
   498    547     int iLabel;                     /* Label resolved to end of generated code */
          548  +  u8 opSeek;                      /* Seek opcode */
   499    549   
   500    550     /* Vdbe is guaranteed to have been allocated by this stage. */
   501    551     assert( v );
   502    552   
   503    553     /* Seek cursor iCur to the row to delete. If this row no longer exists 
   504    554     ** (this can happen if a trigger program has already deleted it), do
   505    555     ** not attempt to delete it or fire any DELETE triggers.  */
   506    556     iLabel = sqlite3VdbeMakeLabel(v);
   507         -  sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iPk);
          557  +  opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
          558  +  sqlite3VdbeAddOp4Int(v, opSeek, iCur, iLabel, iPk, nPk);
   508    559    
   509    560     /* If there are any triggers to fire, allocate a range of registers to
   510    561     ** use for the old.* references in the triggers.  */
   511    562     if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
   512    563       u32 mask;                     /* Mask of OLD.* columns in use */
   513    564       int iCol;                     /* Iterator used while populating OLD.* */
   514    565   
................................................................................
   535    586           TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
   536    587       );
   537    588   
   538    589       /* Seek the cursor to the row to be deleted again. It may be that
   539    590       ** the BEFORE triggers coded above have already removed the row
   540    591       ** being deleted. Do not attempt to delete the row a second time, and 
   541    592       ** do not fire AFTER triggers.  */
   542         -    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iPk);
          593  +    sqlite3VdbeAddOp4Int(v, opSeek, iCur, iLabel, iPk, nPk);
   543    594   
   544    595       /* Do FK processing. This call checks that any FK constraints that
   545    596       ** refer to this table (i.e. constraints attached to other tables) 
   546    597       ** are not violated by deleting this row.  */
   547    598       sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0);
   548    599     }
   549    600   
................................................................................
   596    647   */
   597    648   void sqlite3GenerateRowIndexDelete(
   598    649     Parse *pParse,     /* Parsing and code generating context */
   599    650     Table *pTab,       /* Table containing the row to be deleted */
   600    651     int iCur,          /* Cursor number for the table */
   601    652     int *aRegIdx       /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
   602    653   ){
   603         -  int i, iPk = 0;
          654  +  int i;
   604    655     Index *pIdx;
   605    656     int r1;
   606    657     int iPartIdxLabel;
   607    658     Vdbe *v = pParse->pVdbe;
   608    659     Index *pPk;
   609    660   
   610         -  pPk = sqlite3PrimaryKeyIndex(pTab);
          661  +  pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
   611    662     for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
   612    663       if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
   613         -    if( pIdx==pPk ){ iPk = iCur+i; continue; }
          664  +    if( pIdx==pPk ) continue;
   614    665       r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 1, &iPartIdxLabel);
   615    666       sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1,
   616    667                         pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
   617    668       sqlite3VdbeResolveLabel(v, iPartIdxLabel);
   618    669     }
   619         -  if( iPk ){
   620         -    r1 = sqlite3GenerateIndexKey(pParse, pPk, iCur, 0, 1, &iPartIdxLabel);
   621         -    sqlite3VdbeAddOp3(v, OP_IdxDelete, iPk, r1,
   622         -                      pPk->uniqNotNull ? pPk->nKeyCol : pPk->nColumn);
   623         -    sqlite3VdbeResolveLabel(v, iPartIdxLabel);
   624         -  }
   625    670   }
   626    671   
   627    672   /*
   628    673   ** Generate code that will assemble an index key and stores it in register
   629    674   ** regOut.  The key with be for index pIdx which is an index on pTab.
   630    675   ** iCur is the index of a cursor open on the pTab table and pointing to
   631    676   ** the entry that needs indexing.
................................................................................
   673    718     for(j=0; j<nCol; j++){
   674    719       i16 idx = pIdx->aiColumn[j];
   675    720       if( pPk ) idx = sqlite3ColumnOfIndex(pPk, idx);
   676    721       if( idx<0 || idx==pTab->iPKey ){
   677    722         sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+j);
   678    723       }else{
   679    724         sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
   680         -      sqlite3ColumnDefault(v, pTab, idx, -1);
          725  +      sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[j], -1);
   681    726       }
   682    727     }
   683    728     if( regOut ){
   684    729       const char *zAff;
   685    730       if( pTab->pSelect
   686    731        || OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt)
   687    732       ){

Changes to src/insert.c.

    32     32   ){
    33     33     Vdbe *v;
    34     34     assert( !IsVirtual(pTab) );
    35     35     v = sqlite3GetVdbe(p);
    36     36     assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
    37     37     sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
    38     38     if( HasRowid(pTab) ){
    39         -    sqlite3VdbeAddOp4(v, opcode, iCur, pTab->tnum, iDb,
    40         -                      SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32);
           39  +    sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
    41     40       VdbeComment((v, "%s", pTab->zName));
    42     41     }else if( opcode==OP_OpenRead ){
    43     42       Index *pPk = sqlite3PrimaryKeyIndex(pTab);
    44     43       assert( pPk!=0 );
    45     44       assert( pPk->tnum=pTab->tnum );
    46     45       sqlite3VdbeAddOp4(v, opcode, iCur, pPk->tnum, iDb,
    47     46                         (char*)sqlite3IndexKeyinfo(p, pPk), P4_KEYINFO_HANDOFF);
................................................................................
   821    820     }
   822    821   
   823    822     /* If this is not a view, open the table and and all indices */
   824    823     if( !isView ){
   825    824       int nIdx;
   826    825   
   827    826       baseCur = pParse->nTab - withoutRowid;
   828         -    nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite);
          827  +    nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, -1, OP_OpenWrite);
   829    828       aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
   830    829       if( aRegIdx==0 ){
   831    830         goto insert_cleanup;
   832    831       }
   833    832       for(i=0; i<nIdx; i++){
   834    833         aRegIdx[i] = ++pParse->nMem;
   835    834       }
................................................................................
  1407   1406         pParse->ckBase = regData;
  1408   1407         sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrSkipRow,
  1409   1408                            SQLITE_JUMPIFNULL);
  1410   1409         pParse->ckBase = 0;
  1411   1410       }
  1412   1411   
  1413   1412       /* Create a key for accessing the index entry */
  1414         -    regIdx = sqlite3GetTempRange(pParse, pIdx->nKeyCol+1);
         1413  +    regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);
  1415   1414       for(i=0; i<pIdx->nColumn; i++){
  1416   1415         i16 idx = pIdx->aiColumn[i];
  1417   1416         if( idx<0 || idx==pTab->iPKey ){
  1418   1417           sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
  1419   1418         }else{
  1420   1419           sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i);
  1421   1420         }
................................................................................
  1440   1439         if( onError==OE_Ignore ) onError = OE_Replace;
  1441   1440         else if( onError==OE_Fail ) onError = OE_Abort;
  1442   1441       }
  1443   1442       
  1444   1443       /* Check to see if the new index entry will be unique */
  1445   1444       regR = sqlite3GetTempReg(pParse);
  1446   1445       sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
  1447         -    j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,
  1448         -                           regR, SQLITE_INT_TO_PTR(regIdx),
  1449         -                           P4_INT32);
         1446  +    j3 = sqlite3VdbeAddOp4Int(v, OP_IsUnique, baseCur+iCur+1, 0, regR, regIdx);
  1450   1447       sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
  1451   1448   
  1452   1449       /* Generate code that executes if the new index entry is not unique */
  1453   1450       assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
  1454   1451           || onError==OE_Ignore || onError==OE_Replace );
  1455   1452       switch( onError ){
  1456   1453         case OE_Rollback:
................................................................................
  1578   1575   **
  1579   1576   ** Return the number of indices on the table.
  1580   1577   */
  1581   1578   int sqlite3OpenTableAndIndices(
  1582   1579     Parse *pParse,   /* Parsing context */
  1583   1580     Table *pTab,     /* Table to be opened */
  1584   1581     int baseCur,     /* Cursor number assigned to the table */
         1582  +  int pkCur,       /* Cursor number for the primary key */
  1585   1583     int op           /* OP_OpenRead or OP_OpenWrite */
  1586   1584   ){
  1587   1585     int i;
  1588   1586     int iDb;
  1589   1587     Index *pIdx;
  1590   1588     Vdbe *v;
  1591   1589   
................................................................................
  1592   1590     if( IsVirtual(pTab) ) return 0;
  1593   1591     iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
  1594   1592     v = sqlite3GetVdbe(pParse);
  1595   1593     assert( v!=0 );
  1596   1594     sqlite3OpenTable(pParse, baseCur, iDb, pTab, op);
  1597   1595     for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
  1598   1596       KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
         1597  +    int iCur = (pkCur>=0 && pIdx->autoIndex==2) ? pkCur : i+baseCur;
  1599   1598       assert( pIdx->pSchema==pTab->pSchema );
  1600         -    sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb,
         1599  +    sqlite3VdbeAddOp4(v, op, iCur, pIdx->tnum, iDb,
  1601   1600                         (char*)pKey, P4_KEYINFO_HANDOFF);
  1602   1601       VdbeComment((v, "%s", pIdx->zName));
  1603   1602     }
  1604         -  if( pParse->nTab<baseCur+i ){
  1605         -    pParse->nTab = baseCur+i;
  1606         -  }
         1603  +  if( pParse->nTab<=i+baseCur ) pParse->nTab = i+baseCur;
  1607   1604     return i-1;
  1608   1605   }
  1609   1606   
  1610   1607   
  1611   1608   #ifdef SQLITE_TEST
  1612   1609   /*
  1613   1610   ** The following global variable is incremented whenever the

Changes to src/pragma.c.

  1843   1843           int loopTop;
  1844   1844   
  1845   1845           if( pTab->pIndex==0 ) continue;
  1846   1846           addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);  /* Stop if out of errors */
  1847   1847           sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
  1848   1848           sqlite3VdbeJumpHere(v, addr);
  1849   1849           sqlite3ExprCacheClear(pParse);
  1850         -        sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
         1850  +        sqlite3OpenTableAndIndices(pParse, pTab, 1, -1, OP_OpenRead);
  1851   1851           for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
  1852   1852             sqlite3VdbeAddOp2(v, OP_Integer, 0, 7+j); /* index entries counter */
  1853   1853           }
  1854   1854           pParse->nMem = MAX(pParse->nMem, 7+j);
  1855   1855           loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0) + 1;
  1856   1856           for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
  1857   1857             int jmp2, jmp3;

Changes to src/select.c.

  4652   4652           }
  4653   4653           if( pBest ){
  4654   4654             iRoot = pBest->tnum;
  4655   4655             pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
  4656   4656           }
  4657   4657   
  4658   4658           /* Open a read-only cursor, execute the OP_Count, close the cursor. */
  4659         -        sqlite3VdbeAddOp4(v, OP_OpenRead, iCsr, iRoot, iDb, 
  4660         -              SQLITE_INT_TO_PTR(1), P4_INT32);
         4659  +        sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1);
  4661   4660           if( pKeyInfo ){
  4662   4661             sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF);
  4663   4662           }
  4664   4663           sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
  4665   4664           sqlite3VdbeAddOp1(v, OP_Close, iCsr);
  4666   4665           explainSimpleCount(pParse, pTab, pBest);
  4667   4666         }else

Changes to src/sqliteInt.h.

  2916   2916   int sqlite3IsRowid(const char*);
  2917   2917   void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,i16,u8,u8);
  2918   2918   void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
  2919   2919   int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*);
  2920   2920   void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
  2921   2921                                        int*,int,int,int,int,int*);
  2922   2922   void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
  2923         -int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
         2923  +int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, int);
  2924   2924   void sqlite3BeginWriteOperation(Parse*, int, int);
  2925   2925   void sqlite3MultiWrite(Parse*);
  2926   2926   void sqlite3MayAbort(Parse*);
  2927   2927   void sqlite3HaltConstraint(Parse*, int, int, char*, int);
  2928   2928   Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
  2929   2929   ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
  2930   2930   SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);

Changes to src/vdbe.c.

  3677   3677       if( pOp->p4.i==0 ){
  3678   3678         sqlite3DbFree(db, pFree);
  3679   3679       }
  3680   3680       if( rc!=SQLITE_OK ){
  3681   3681         break;
  3682   3682       }
  3683   3683       alreadyExists = (res==0);
         3684  +    pC->nullRow = 1-alreadyExists;
  3684   3685       pC->deferredMoveto = 0;
  3685   3686       pC->cacheStatus = CACHE_STALE;
  3686   3687     }
  3687   3688     if( pOp->opcode==OP_Found ){
  3688   3689       if( alreadyExists ) pc = pOp->p2 - 1;
  3689   3690     }else{
  3690   3691       if( !alreadyExists ) pc = pOp->p2 - 1;
................................................................................
  3777   3778       }
  3778   3779     }
  3779   3780     break;
  3780   3781   }
  3781   3782   
  3782   3783   /* Opcode: NotExists P1 P2 P3 * *
  3783   3784   **
  3784         -** Use the content of register P3 as an integer key.  If a record 
  3785         -** with that key does not exist in table of P1, then jump to P2. 
  3786         -** If the record does exist, then fall through.  The cursor is left 
  3787         -** pointing to the record if it exists.
         3785  +** P1 is the index of a cursor open on an SQL table btree (with integer
         3786  +** keys).  P3 is an integer rowid.  If P1 does not contain a record with
         3787  +** rowid P3 then jump immediately to P2.  If P1 does contain a record
         3788  +** with rowid P3 then leave the cursor pointing at that record and fall
         3789  +** through to the next instruction.
  3788   3790   **
  3789         -** The difference between this operation and NotFound is that this
  3790         -** operation assumes the key is an integer and that P1 is a table whereas
  3791         -** NotFound assumes key is a blob constructed from MakeRecord and
  3792         -** P1 is an index.
         3791  +** The OP_NotFound opcode performs the same operation on index btrees
         3792  +** (with arbitrary multi-value keys).
  3793   3793   **
  3794   3794   ** See also: Found, NotFound, IsUnique
  3795   3795   */
  3796   3796   case OP_NotExists: {        /* jump, in3 */
  3797   3797     VdbeCursor *pC;
  3798   3798     BtCursor *pCrsr;
  3799   3799     int res;

Changes to src/where.c.

  3561   3561       }else{
  3562   3562         Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
  3563   3563         iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
  3564   3564         for(j=0; j<pPk->nKeyCol; j++){
  3565   3565           k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
  3566   3566           sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
  3567   3567         }
  3568         -      sqlite3VdbeAddOp4(v, OP_NotFound, iCur, addrCont, iRowidReg, 
  3569         -                        SQLITE_INT_TO_PTR(pPk->nKeyCol), P4_INT32);
         3568  +      sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
         3569  +                           iRowidReg, pPk->nKeyCol);
  3570   3570       }
  3571   3571   
  3572   3572       /* Record the instruction used to terminate the loop. Disable 
  3573   3573       ** WHERE clause terms made redundant by the index range scan.
  3574   3574       */
  3575   3575       if( pLoop->wsFlags & WHERE_ONEROW ){
  3576   3576         pLevel->op = OP_Noop;
................................................................................
  4599   4599           pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
  4600   4600         }
  4601   4601   
  4602   4602         /* Full scan via index */
  4603   4603         if( b
  4604   4604          || ( m==0
  4605   4605            && pProbe->bUnordered==0
  4606         -         && pProbe->szIdxRow<pTab->szTabRow
         4606  +         && (!HasRowid(pTab) || pProbe->szIdxRow<pTab->szTabRow)
  4607   4607            && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
  4608   4608            && sqlite3GlobalConfig.bUseCis
  4609   4609            && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
  4610   4610             )
  4611   4611         ){
  4612   4612           pNew->iSortIdx = b ? iSortIdx : 0;
  4613   4613           if( m==0 ){