/ Check-in [67602e40]
Login

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

Overview
Comment:Add the unpacked key fields to OP_IdxInsert for INSERT and UPDATE statements.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | unpacked-IdxInsert
Files: files | file ages | folders
SHA1: 67602e40f122cbb6354048a64c5d3a72b2855ec7
User & Date: drh 2016-11-10 14:24:04
Context
2016-11-10
16:07
Remove C++ style comments. No code changes. check-in: 42f8aa62 user: drh tags: unpacked-IdxInsert
14:24
Add the unpacked key fields to OP_IdxInsert for INSERT and UPDATE statements. check-in: 67602e40 user: drh tags: unpacked-IdxInsert
2016-11-09
20:14
Comment changes that attempt to better explain the behavior of the "seekResult" field on VdbeCursor objects and the seekResult parameter to sqlite3BtreeInsert() and the OPFLAG_USESEEKRESULT flag on insert opcodes. No changes to code. check-in: 345b46be user: drh tags: unpacked-IdxInsert
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/insert.c.

   782    782       regRowCount = ++pParse->nMem;
   783    783       sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
   784    784     }
   785    785   
   786    786     /* If this is not a view, open the table and and all indices */
   787    787     if( !isView ){
   788    788       int nIdx;
          789  +    Index *pIdx;
   789    790       nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
   790    791                                         &iDataCur, &iIdxCur);
   791    792       aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1));
   792    793       if( aRegIdx==0 ){
   793    794         goto insert_cleanup;
   794    795       }
   795         -    for(i=0; i<nIdx; i++){
          796  +    for(i=0, pIdx=pTab->pIndex; i<nIdx; pIdx=pIdx->pNext, i++){
          797  +      assert( pIdx );
   796    798         aRegIdx[i] = ++pParse->nMem;
          799  +      pParse->nMem += pIdx->nColumn;
   797    800       }
   798    801     }
   799    802   
   800    803     /* This is the top of the main insertion loop */
   801    804     if( useTempTable ){
   802    805       /* This block codes the top of loop only.  The complete loop is the
   803    806       ** following pseudocode (template 4):
................................................................................
  1508   1511                               SQLITE_JUMPIFNULL);
  1509   1512         pParse->ckBase = 0;
  1510   1513       }
  1511   1514   
  1512   1515       /* Create a record for this index entry as it should appear after
  1513   1516       ** the insert or update.  Store that record in the aRegIdx[ix] register
  1514   1517       */
  1515         -    regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
         1518  +    regIdx = aRegIdx[ix]+1; // sqlite3GetTempRange(pParse, pIdx->nColumn);
  1516   1519       for(i=0; i<pIdx->nColumn; i++){
  1517   1520         int iField = pIdx->aiColumn[i];
  1518   1521         int x;
  1519   1522         if( iField==XN_EXPR ){
  1520   1523           pParse->ckBase = regNewData+1;
  1521   1524           sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
  1522   1525           pParse->ckBase = 0;
................................................................................
  1545   1548         sqlite3VdbeResolveLabel(v, addrUniqueOk);
  1546   1549         continue;
  1547   1550       }
  1548   1551   
  1549   1552       /* Find out what action to take in case there is a uniqueness conflict */
  1550   1553       onError = pIdx->onError;
  1551   1554       if( onError==OE_None ){ 
  1552         -      sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
         1555  +//      sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
  1553   1556         sqlite3VdbeResolveLabel(v, addrUniqueOk);
  1554   1557         continue;  /* pIdx is not a UNIQUE index */
  1555   1558       }
  1556   1559       if( overrideError!=OE_Default ){
  1557   1560         onError = overrideError;
  1558   1561       }else if( onError==OE_Default ){
  1559   1562         onError = OE_Abort;
................................................................................
  1644   1647               regR, nPkField, 0, OE_Replace,
  1645   1648               (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), -1);
  1646   1649           seenReplace = 1;
  1647   1650           break;
  1648   1651         }
  1649   1652       }
  1650   1653       sqlite3VdbeResolveLabel(v, addrUniqueOk);
  1651         -    sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
         1654  +    // sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
  1652   1655       if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
  1653   1656     }
  1654   1657     if( ipkTop ){
  1655   1658       sqlite3VdbeGoto(v, ipkTop+1);
  1656   1659       sqlite3VdbeJumpHere(v, ipkBottom);
  1657   1660     }
  1658   1661     
................................................................................
  1694   1697     for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
  1695   1698       if( aRegIdx[i]==0 ) continue;
  1696   1699       bAffinityDone = 1;
  1697   1700       if( pIdx->pPartIdxWhere ){
  1698   1701         sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
  1699   1702         VdbeCoverage(v);
  1700   1703       }
  1701         -    sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
         1704  +    sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
         1705  +                         aRegIdx[i]+1, pIdx->nColumn);
  1702   1706       pik_flags = 0;
  1703   1707       if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
  1704   1708       if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
  1705   1709         assert( pParse->nested==0 );
  1706   1710         pik_flags |= OPFLAG_NCHANGE;
  1707   1711       }
  1708   1712       sqlite3VdbeChangeP5(v, pik_flags);

Changes to src/update.c.

   278    278     **
   279    279     ** FIXME:  Be smarter about omitting indexes that use expressions.
   280    280     */
   281    281     for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
   282    282       int reg;
   283    283       if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){
   284    284         reg = ++pParse->nMem;
          285  +      pParse->nMem += pIdx->nColumn;
   285    286       }else{
   286    287         reg = 0;
   287    288         for(i=0; i<pIdx->nKeyCol; i++){
   288    289           i16 iIdxCol = pIdx->aiColumn[i];
   289    290           if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
   290    291             reg = ++pParse->nMem;
          292  +          pParse->nMem += pIdx->nColumn;
   291    293             break;
   292    294           }
   293    295         }
   294    296       }
   295    297       if( reg==0 ) aToOpen[j+1] = 0;
   296    298       aRegIdx[j] = reg;
   297    299     }