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

Overview
Comment:Combine the OP_IdxInsert, OP_SorterInsert, and OP_Insert opcodes into the single OP_Insert opcode.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3b7caafe8c7aff25805e388331ab956f88336510
User & Date: drh 2013-07-30 01:30:31.884
Context
2013-07-30
02:11
Provide more detail in the P4 column in EXPLAIN output. check-in: 34abc4149f user: drh tags: trunk
01:30
Combine the OP_IdxInsert, OP_SorterInsert, and OP_Insert opcodes into the single OP_Insert opcode. check-in: 3b7caafe8c user: drh tags: trunk
2013-07-29
20:26
Change the name of Column.isPrimKey to Column.iPrimKey, make it a u16, and make it hold the integer column number of the column within the primary key. check-in: 6d33ce14cd user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
    {
      int tnum = firstAvailableTableNumber(db, iDb);
      sqlite4VdbeAddOp2(v, OP_Integer, tnum, reg2);
    }
#endif
    sqlite4OpenMasterTable(pParse, iDb);
    sqlite4VdbeAddOp2(v, OP_NewRowid, 0, reg1);
    sqlite4VdbeAddOp2(v, OP_Null, 0, reg3);
    sqlite4VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
    sqlite4VdbeChangeP5(v, OPFLAG_APPEND);
    sqlite4VdbeAddOp0(v, OP_Close);
  }

  /* Normal (non-error) return. */
  return;








<
|







819
820
821
822
823
824
825

826
827
828
829
830
831
832
833
    {
      int tnum = firstAvailableTableNumber(db, iDb);
      sqlite4VdbeAddOp2(v, OP_Integer, tnum, reg2);
    }
#endif
    sqlite4OpenMasterTable(pParse, iDb);
    sqlite4VdbeAddOp2(v, OP_NewRowid, 0, reg1);

    sqlite4VdbeAddOp3(v, OP_Insert, 0, 0, reg1);
    sqlite4VdbeChangeP5(v, OPFLAG_APPEND);
    sqlite4VdbeAddOp0(v, OP_Close);
  }

  /* Normal (non-error) return. */
  return;

2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
      sqlite4HaltConstraint(pParse, OE_Abort, (char *)zErr, P4_STATIC);
      sqlite4VdbeJumpHere(v, addrTest);
    }
    if( pIdx->nCover>0 ){
      regData = regKey+1;
      sqlite4EncodeIndexValue(pParse, iTab, pIdx, regData);
    }
    sqlite4VdbeAddOp3(v, OP_IdxInsert, iIdx, regData, regKey);  
    sqlite4ReleaseTempRange(pParse, regKey, 2);
  }

  sqlite4VdbeAddOp2(v, OP_Next, iTab, addr1+1);
  sqlite4VdbeJumpHere(v, addr1);

  sqlite4VdbeAddOp1(v, OP_Close, iTab);







|







2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
      sqlite4HaltConstraint(pParse, OE_Abort, (char *)zErr, P4_STATIC);
      sqlite4VdbeJumpHere(v, addrTest);
    }
    if( pIdx->nCover>0 ){
      regData = regKey+1;
      sqlite4EncodeIndexValue(pParse, iTab, pIdx, regData);
    }
    sqlite4VdbeAddOp3(v, OP_Insert, iIdx, regData, regKey);  
    sqlite4ReleaseTempRange(pParse, regKey, 2);
  }

  sqlite4VdbeAddOp2(v, OP_Next, iTab, addr1+1);
  sqlite4VdbeJumpHere(v, addr1);

  sqlite4VdbeAddOp1(v, OP_Close, iTab);
Changes to src/expr.c.
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784

          /* Evaluate the expression and insert it into the temp table */
          r3 = sqlite4ExprCodeTarget(pParse, pE2, r1);
          r4 = sqlite4GetTempReg(pParse);
          sqlite4VdbeAddOp2(v, OP_MakeKey, pExpr->iTable, r4);
          sqlite4VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
          sqlite4ExprCacheAffinityChange(pParse, r3, 1);
          sqlite4VdbeAddOp3(v, OP_IdxInsert, pExpr->iTable, r2, r4);
          sqlite4ReleaseTempReg(pParse, r4);
        }
        sqlite4ReleaseTempReg(pParse, r1);
        sqlite4ReleaseTempReg(pParse, r2);
      }
      sqlite4VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
      break;







|







1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784

          /* Evaluate the expression and insert it into the temp table */
          r3 = sqlite4ExprCodeTarget(pParse, pE2, r1);
          r4 = sqlite4GetTempReg(pParse);
          sqlite4VdbeAddOp2(v, OP_MakeKey, pExpr->iTable, r4);
          sqlite4VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
          sqlite4ExprCacheAffinityChange(pParse, r3, 1);
          sqlite4VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r4);
          sqlite4ReleaseTempReg(pParse, r4);
        }
        sqlite4ReleaseTempReg(pParse, r1);
        sqlite4ReleaseTempReg(pParse, r2);
      }
      sqlite4VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
      break;
Changes to src/insert.c.
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
              v, OP_Permutation, pIdx->nCover, 0, 0,
              (char*)aiPermute, P4_INTARRAY
          );
        }
        regData = regCover;
        sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pIdx->nCover, regData);
      }
      sqlite4VdbeAddOp3(v, OP_IdxInsert, baseCur+i, regData, aRegIdx[i]);
      sqlite4VdbeChangeP5(v, flags);
    }
  }
}

/*
** Generate code that will open cursors for a table and for all







|







1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
              v, OP_Permutation, pIdx->nCover, 0, 0,
              (char*)aiPermute, P4_INTARRAY
          );
        }
        regData = regCover;
        sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pIdx->nCover, regData);
      }
      sqlite4VdbeAddOp3(v, OP_Insert, baseCur+i, regData, aRegIdx[i]);
      sqlite4VdbeChangeP5(v, flags);
    }
  }
}

/*
** Generate code that will open cursors for a table and for all
Changes to src/lsm_log.c.
1128
1129
1130
1131
1132
1133
1134
1135
1136
void lsmLogClose(lsm_db *db){
  if( db->pLogWriter ){
    lsmFree(db->pEnv, db->pLogWriter->buf.z);
    lsmFree(db->pEnv, db->pLogWriter);
    db->pLogWriter = 0;
  }
}









<
<
1128
1129
1130
1131
1132
1133
1134


void lsmLogClose(lsm_db *db){
  if( db->pLogWriter ){
    lsmFree(db->pEnv, db->pLogWriter->buf.z);
    lsmFree(db->pEnv, db->pLogWriter);
    db->pLogWriter = 0;
  }
}


Changes to src/lsm_main.c.
1003
1004
1005
1006
1007
1008
1009
1010
1011
    }else{
      lsm_rollback(pDb, 0);
    }
  }

  return rc;
}









<
<
1003
1004
1005
1006
1007
1008
1009


    }else{
      lsm_rollback(pDb, 0);
    }
  }

  return rc;
}


Changes to src/lsm_shared.c.
1961
1962
1963
1964
1965
1966
1967
1968
      nKB = (((i64)nWrite * lsmFsPageSize(pDb->pFS)) + 1023) / 1024;
    }
    *pnKB = nKB;
  }

  return rc;
}








<
1961
1962
1963
1964
1965
1966
1967

      nKB = (((i64)nWrite * lsmFsPageSize(pDb->pFS)) + 1023) / 1024;
    }
    *pnKB = nKB;
  }

  return rc;
}

Changes to src/mem.c.
776
777
778
779
780
781
782
783
784
  return sqlite4_buffer_append(pBuf, p, n);
}

void sqlite4_buffer_clear(sqlite4_buffer *pBuf){
  sqlite4_mm_free(pBuf->pMM, pBuf->p);
  sqlite4_buffer_init(pBuf, pBuf->pMM);
}









<
<
776
777
778
779
780
781
782


  return sqlite4_buffer_append(pBuf, p, n);
}

void sqlite4_buffer_clear(sqlite4_buffer *pBuf){
  sqlite4_mm_free(pBuf->pMM, pBuf->p);
  sqlite4_buffer_init(pBuf, pBuf->pMM);
}


Changes to src/pragma.c.
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
                         r1, "key may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r1);
    r2 = sqlite4ExprCodeTarget(pParse, pList->a[1].pExpr, 2);
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r2, "value may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r2);
    sqlite4VdbeAddOp0(v, OP_OpenWrite);
    sqlite4VdbeAddOp3(v, OP_IdxInsert, 0, r2, r1);
    sqlite4VdbeAddOp0(v, OP_Halt);
  }else
#endif /* SQLITE4_DEBUG

  /*
  **   PRAGMA integrity_check
  **







|







658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
                         r1, "key may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r1);
    r2 = sqlite4ExprCodeTarget(pParse, pList->a[1].pExpr, 2);
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r2, "value may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r2);
    sqlite4VdbeAddOp0(v, OP_OpenWrite);
    sqlite4VdbeAddOp3(v, OP_Insert, 0, r2, r1);
    sqlite4VdbeAddOp0(v, OP_Halt);
  }else
#endif /* SQLITE4_DEBUG

  /*
  **   PRAGMA integrity_check
  **
Changes to src/select.c.
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
  Select *pSelect,                /* The whole SELECT statement */
  int regData                     /* Register holding data to be sorted */
){
  Vdbe *v = pParse->pVdbe;
  int nExpr = pOrderBy->nExpr;
  int regBase = sqlite4GetTempRange(pParse, nExpr+1);
  int regKey = sqlite4GetTempReg(pParse);
  int op;

  /* Assemble the sort-key values in a contiguous array of registers
  ** starting at regBase. The sort-key consists of the result of each 
  ** expression in the ORDER BY clause followed by a unique sequence 
  ** number. The sequence number allows more than one row with the same
  ** sort-key.  */
  sqlite4ExprCacheClear(pParse);
  sqlite4ExprCodeExprList(pParse, pOrderBy, regBase, 0);
  sqlite4VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);

  /* Encode the sort-key. */
  sqlite4VdbeAddOp3(v, OP_MakeIdxKey, pOrderBy->iECursor, regBase, regKey);

  /* Insert an entry into the sorter. The key inserted is the encoded key
  ** created by the OP_MakeIdxKey coded above. The value is the record
  ** currently stored in register regData.  */
  if( pSelect->selFlags & SF_UseSorter ){
    op = OP_SorterInsert;
  }else{
    op = OP_IdxInsert;
  }
  sqlite4VdbeAddOp3(v, op, pOrderBy->iECursor, regData, regKey);

  /* Release the temporary registers */
  sqlite4ReleaseTempReg(pParse, regKey);
  sqlite4ReleaseTempRange(pParse, regBase, nExpr+1);

  if( pSelect->iLimit ){
    int addr1, addr2;







<
















<
<
<
<
<
|







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
  Select *pSelect,                /* The whole SELECT statement */
  int regData                     /* Register holding data to be sorted */
){
  Vdbe *v = pParse->pVdbe;
  int nExpr = pOrderBy->nExpr;
  int regBase = sqlite4GetTempRange(pParse, nExpr+1);
  int regKey = sqlite4GetTempReg(pParse);


  /* Assemble the sort-key values in a contiguous array of registers
  ** starting at regBase. The sort-key consists of the result of each 
  ** expression in the ORDER BY clause followed by a unique sequence 
  ** number. The sequence number allows more than one row with the same
  ** sort-key.  */
  sqlite4ExprCacheClear(pParse);
  sqlite4ExprCodeExprList(pParse, pOrderBy, regBase, 0);
  sqlite4VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);

  /* Encode the sort-key. */
  sqlite4VdbeAddOp3(v, OP_MakeIdxKey, pOrderBy->iECursor, regBase, regKey);

  /* Insert an entry into the sorter. The key inserted is the encoded key
  ** created by the OP_MakeIdxKey coded above. The value is the record
  ** currently stored in register regData.  */





  sqlite4VdbeAddOp3(v, OP_Insert, pOrderBy->iECursor, regData, regKey);

  /* Release the temporary registers */
  sqlite4ReleaseTempReg(pParse, regKey);
  sqlite4ReleaseTempRange(pParse, regBase, nExpr+1);

  if( pSelect->iLimit ){
    int addr1, addr2;
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523

  v = pParse->pVdbe;
  r1 = sqlite4GetTempReg(pParse);
  r2 = sqlite4GetTempReg(pParse);
  sqlite4VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N);
  sqlite4VdbeAddOp2(v, OP_MakeKey, iTab, r2);
  sqlite4VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
  sqlite4VdbeAddOp3(v, OP_IdxInsert, iTab, r1, r2);
  sqlite4ReleaseTempReg(pParse, r1);
  sqlite4ReleaseTempReg(pParse, r2);
}

#ifndef SQLITE4_OMIT_SUBQUERY
/*
** Generate an error message when a SELECT is used within a subexpression







|







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517

  v = pParse->pVdbe;
  r1 = sqlite4GetTempReg(pParse);
  r2 = sqlite4GetTempReg(pParse);
  sqlite4VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N);
  sqlite4VdbeAddOp2(v, OP_MakeKey, iTab, r2);
  sqlite4VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
  sqlite4VdbeAddOp3(v, OP_Insert, iTab, r1, r2);
  sqlite4ReleaseTempReg(pParse, r1);
  sqlite4ReleaseTempReg(pParse, r2);
}

#ifndef SQLITE4_OMIT_SUBQUERY
/*
** Generate an error message when a SELECT is used within a subexpression
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
#ifndef SQLITE4_OMIT_COMPOUND_SELECT
    case SRT_Union: {
      int r1, r2;
      r1 = sqlite4GetTempReg(pParse);
      r2 = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp2(v, OP_MakeKey, iParm, r2);
      sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
      sqlite4VdbeAddOp3(v, OP_IdxInsert, iParm, r1, r2);
      sqlite4ReleaseTempReg(pParse, r1);
      sqlite4ReleaseTempReg(pParse, r2);
      break;
    }

    /* This is used for processing queries of the form:
    **







|







621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
#ifndef SQLITE4_OMIT_COMPOUND_SELECT
    case SRT_Union: {
      int r1, r2;
      r1 = sqlite4GetTempReg(pParse);
      r2 = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp2(v, OP_MakeKey, iParm, r2);
      sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
      sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
      sqlite4ReleaseTempReg(pParse, r1);
      sqlite4ReleaseTempReg(pParse, r2);
      break;
    }

    /* This is used for processing queries of the form:
    **
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
        sqlite4VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
        pushOntoSorter(pParse, pOrderBy, p, r1);
      }else{
        int r2 = sqlite4GetTempReg(pParse);
        sqlite4VdbeAddOp2(v, OP_MakeKey, iParm, r2);
        sqlite4VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
        sqlite4ExprCacheAffinityChange(pParse, regResult, 1);
        sqlite4VdbeAddOp3(v, OP_IdxInsert, iParm, r1, r2);
        sqlite4ReleaseTempReg(pParse, r2);
      }
      sqlite4ReleaseTempReg(pParse, r1);
      break;
    }

    /* If any row exist in the result set, record that fact and abort.







|







685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
        sqlite4VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
        pushOntoSorter(pParse, pOrderBy, p, r1);
      }else{
        int r2 = sqlite4GetTempReg(pParse);
        sqlite4VdbeAddOp2(v, OP_MakeKey, iParm, r2);
        sqlite4VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
        sqlite4ExprCacheAffinityChange(pParse, regResult, 1);
        sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
        sqlite4ReleaseTempReg(pParse, r2);
      }
      sqlite4ReleaseTempReg(pParse, r1);
      break;
    }

    /* If any row exist in the result set, record that fact and abort.
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
#ifndef SQLITE4_OMIT_SUBQUERY
    case SRT_Set: {
      assert( nColumn==1 );
      int regKey = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp2(v, OP_MakeKey, iParm, regKey);
      sqlite4VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
      sqlite4ExprCacheAffinityChange(pParse, regRow, 1);
      sqlite4VdbeAddOp3(v, OP_IdxInsert, iParm, regRowid, regKey);
      sqlite4ReleaseTempReg(pParse, regKey);
      break;
    }
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite4VdbeAddOp3(v, OP_Column, iTab, 0, iParm);
      /* The LIMIT clause will terminate the loop for us */







|







961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
#ifndef SQLITE4_OMIT_SUBQUERY
    case SRT_Set: {
      assert( nColumn==1 );
      int regKey = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp2(v, OP_MakeKey, iParm, regKey);
      sqlite4VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
      sqlite4ExprCacheAffinityChange(pParse, regRow, 1);
      sqlite4VdbeAddOp3(v, OP_Insert, iParm, regRowid, regKey);
      sqlite4ReleaseTempReg(pParse, regKey);
      break;
    }
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite4VdbeAddOp3(v, OP_Column, iTab, 0, iParm);
      /* The LIMIT clause will terminate the loop for us */
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
      p->affinity = 
         sqlite4CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity);
      r1 = sqlite4GetTempReg(pParse);
      r2 = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp2(v, OP_MakeKey, pDest->iParm, r2);
      sqlite4VdbeAddOp4(v, OP_MakeRecord, pIn->iMem, 1, r1, &p->affinity, 1);
      sqlite4ExprCacheAffinityChange(pParse, pIn->iMem, 1);
      sqlite4VdbeAddOp3(v, OP_IdxInsert, pDest->iParm, r1, r2);
      sqlite4ReleaseTempReg(pParse, r1);
      sqlite4ReleaseTempReg(pParse, r2);
      break;
    }

#if 0  /* Never occurs on an ORDER BY query */
    /* If any row exist in the result set, record that fact and abort.







|







2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
      p->affinity = 
         sqlite4CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity);
      r1 = sqlite4GetTempReg(pParse);
      r2 = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp2(v, OP_MakeKey, pDest->iParm, r2);
      sqlite4VdbeAddOp4(v, OP_MakeRecord, pIn->iMem, 1, r1, &p->affinity, 1);
      sqlite4ExprCacheAffinityChange(pParse, pIn->iMem, 1);
      sqlite4VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2);
      sqlite4ReleaseTempReg(pParse, r1);
      sqlite4ReleaseTempReg(pParse, r2);
      break;
    }

#if 0  /* Never occurs on an ORDER BY query */
    /* If any row exist in the result set, record that fact and abort.
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
          sqlite4VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
          sqlite4ReleaseTempRange(pParse, regBase, nCol);
        }

        /* Insert the key/value into the sorting index and end the loop
        ** generated by where.c code.  */
        sqlite4VdbeAddOp3(
            v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord, regKey
        );
        sqlite4WhereEnd(pWInfo);

        sqlite4VdbeAddOp2(v, OP_Null, 0, regKey);
        sqlite4VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
        VdbeComment((v, "GROUP BY sort"));
        sAggInfo.useSortingIdx = 1;







|







4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
          sqlite4VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
          sqlite4ReleaseTempRange(pParse, regBase, nCol);
        }

        /* Insert the key/value into the sorting index and end the loop
        ** generated by where.c code.  */
        sqlite4VdbeAddOp3(
            v, OP_Insert, sAggInfo.sortingIdx, regRecord, regKey
        );
        sqlite4WhereEnd(pWInfo);

        sqlite4VdbeAddOp2(v, OP_Null, 0, regKey);
        sqlite4VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
        VdbeComment((v, "GROUP BY sort"));
        sAggInfo.useSortingIdx = 1;
Changes to src/vdbe.c.
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
    i1 = iMax+1;
  }
  pIn1->u.num = sqlite4_num_from_int64(i1);

  break;
}

/* Opcode: Insert P1 P2 P3 P4 P5
**
** Write an entry into the table of cursor P1.  A new entry is
** created if it doesn't already exist or the data for an existing
** entry is overwritten.  The data is the value MEM_Blob stored in register
** number P2. The key is stored in register P3. The key must
** be a MEM_Int.
**
** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
** incremented (otherwise not).  If the OPFLAG_LASTROWID flag of P5 is set,
** then rowid is stored for subsequent return by the
** sqlite4_last_insert_rowid() function (otherwise it is unmodified).
**
** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
** UPDATE operation.  Otherwise (if the flag is clear) then this opcode
** is part of an INSERT operation.  The difference is only important to
** the update hook.
**
** Parameter P4 may point to a string containing the table-name, or 
** may be NULL. If it is not NULL, then the update-hook 
** (sqlite4.xUpdateCallback) is invoked following a successful insert.
**
** (WARNING/TODO: If P1 is a pseudo-cursor and P2 is dynamically
** allocated, then ownership of P2 is transferred to the pseudo-cursor
** and register P2 becomes ephemeral.  If the cursor is changed, the
** value of register P2 will then change.  Make sure this does not
** cause any problems.)
**
** This instruction only works on tables.  The equivalent instruction
** for indices is OP_IdxInsert.
*/
case OP_Insert: {
  Mem *pData;       /* MEM cell holding data for the record to be inserted */
  Mem *pKey;        /* MEM cell holding key  for the record */
  i64 iKey;         /* The integer ROWID or key for the record to be inserted */
  VdbeCursor *pC;   /* Cursor to table into which insert is written */
  int n;
  KVByteArray aKey[24];

  pData = &aMem[pOp->p2];
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( memIsValid(pData) );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  REGISTER_TRACE(pOp->p2, pData);

  pKey = &aMem[pOp->p3];
  assert( pKey->flags & MEM_Int );
  assert( memIsValid(pKey) );
  REGISTER_TRACE(pOp->p3, pKey);
  iKey = sqlite4_num_to_int64(pKey->u.num, 0);

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
  if( pData->flags & MEM_Null ){
    pData->z = 0;
    pData->n = 0;
  }else{
    assert( pData->flags & (MEM_Blob|MEM_Str) );
  }
  n = sqlite4PutVarint64(aKey, pC->iRoot);
  n += sqlite4VdbeEncodeIntKey(&aKey[n], iKey);
  rc = sqlite4KVStoreReplace(pC->pKVCur->pStore, aKey, n,
                             (const KVByteArray*)pData->z, pData->n);
  pC->rowChnged = 1;

  break;
}

/* Opcode: Delete P1 P2 * * *
**
** Delete the record at which the P1 cursor is currently pointing.
**
** The cursor will be left pointing at either the next or the previous
** record in the table. If it is left pointing at the next record, then
** the next Next instruction will be a no-op.  Hence it is OK to delete







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







3370
3371
3372
3373
3374
3375
3376




































































3377
3378
3379
3380
3381
3382
3383
    i1 = iMax+1;
  }
  pIn1->u.num = sqlite4_num_from_int64(i1);

  break;
}





































































/* Opcode: Delete P1 P2 * * *
**
** Delete the record at which the P1 cursor is currently pointing.
**
** The cursor will be left pointing at either the next or the previous
** record in the table. If it is left pointing at the next record, then
** the next Next instruction will be a no-op.  Hence it is OK to delete
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874




3875
3876
3877
3878
3879
3880
3881
3882
3883




3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894










3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
    pC->nullRow = 1;
    rc = SQLITE4_OK;
  }
  break;
}


/* Opcode: SorterInsert P1 P2 P3
*/
/* Opcode: IdxInsert P1 P2 P3 * P5
**
** Register P3 holds the key and register P2 holds the data for an
** index entry.  Write this record into the index specified by the
** cursor P1.




**
** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
** incremented (otherwise not).
*/
case OP_SorterInsert:
case OP_IdxInsert: {
  VdbeCursor *pC;
  Mem *pKey;
  Mem *pData;





  pC = p->apCsr[pOp->p1];
  pKey = &aMem[pOp->p3];
  pData = pOp->p2 ? &aMem[pOp->p2] : 0;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pC && pC->pKVCur && pC->pKVCur->pStore );
  assert( pKey->flags & MEM_Blob );
  assert( pData==0 || (pData->flags & MEM_Blob) );

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;











  rc = sqlite4KVStoreReplace(
     pC->pKVCur->pStore,
     (u8 *)pKey->z, pKey->n,
     (u8 *)(pData ? pData->z : 0), (pData ? pData->n : 0)
  );
  pC->rowChnged = 1;

  break;
}








<
<
|




>
>
>
>




<
|



>
>
>
>







<



>
>
>
>
>
>
>
>
>
>



|







3793
3794
3795
3796
3797
3798
3799


3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812

3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827

3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
    pC->nullRow = 1;
    rc = SQLITE4_OK;
  }
  break;
}




/* Opcode: Insert P1 P2 P3 * P5
**
** Register P3 holds the key and register P2 holds the data for an
** index entry.  Write this record into the index specified by the
** cursor P1.
**
** P3 can be either an integer or a blob.  If it is a blob then its value
** is used as-is as the KVStore key.  If P3 is an integer, then the KVStore
** key is constructed using P3 as the INTEGER PRIMARY KEY value.
**
** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
** incremented (otherwise not).
*/

case OP_Insert: {
  VdbeCursor *pC;
  Mem *pKey;
  Mem *pData;
  int nKVKey;
  KVByteArray *pKVKey;
  KVByteArray aKey[24];
  

  pC = p->apCsr[pOp->p1];
  pKey = &aMem[pOp->p3];
  pData = pOp->p2 ? &aMem[pOp->p2] : 0;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pC && pC->pKVCur && pC->pKVCur->pStore );

  assert( pData==0 || (pData->flags & MEM_Blob) );

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;

  if( pKey->flags & MEM_Int ){
    nKVKey = sqlite4PutVarint64(aKey, pC->iRoot);
    nKVKey += sqlite4VdbeEncodeIntKey(aKey+nKVKey, sqlite4VdbeIntValue(pKey));
    pKVKey = aKey;
  }else{
    nKVKey = pKey->n;
    pKVKey = pKey->z;
  }


  rc = sqlite4KVStoreReplace(
     pC->pKVCur->pStore,
     (u8 *)pKVKey, nKVKey,
     (u8 *)(pData ? pData->z : 0), (pData ? pData->n : 0)
  );
  pC->rowChnged = 1;

  break;
}

Changes to src/where.c.
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
  /* Fill the automatic index with content */
  iPkCsr = pLevel->iTabCur;
  addrTop = sqlite4VdbeAddOp1(v, OP_Rewind, iPkCsr);
  regRecord = sqlite4GetTempRange(pParse, 2);
  regKey = regRecord + 1;
  sqlite4EncodeIndexKey(pParse, 0, iPkCsr, pIdx, pLevel->iIdxCur, 1, regKey);
  sqlite4EncodeIndexValue(pParse, iPkCsr, pIdx, regRecord);
  sqlite4VdbeAddOp3(v, OP_IdxInsert, pLevel->iIdxCur, regRecord, regKey);
  /* sqlite4VdbeChangeP5(v, OPFLAG_USESEEKRESULT); */
  sqlite4VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
  sqlite4VdbeChangeP5(v, SQLITE4_STMTSTATUS_AUTOINDEX);
  sqlite4VdbeJumpHere(v, addrTop);
  sqlite4ReleaseTempRange(pParse, regRecord, 2);
  
  /* Jump here when skipping the initialization */







|







2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
  /* Fill the automatic index with content */
  iPkCsr = pLevel->iTabCur;
  addrTop = sqlite4VdbeAddOp1(v, OP_Rewind, iPkCsr);
  regRecord = sqlite4GetTempRange(pParse, 2);
  regKey = regRecord + 1;
  sqlite4EncodeIndexKey(pParse, 0, iPkCsr, pIdx, pLevel->iIdxCur, 1, regKey);
  sqlite4EncodeIndexValue(pParse, iPkCsr, pIdx, regRecord);
  sqlite4VdbeAddOp3(v, OP_Insert, pLevel->iIdxCur, regRecord, regKey);
  /* sqlite4VdbeChangeP5(v, OPFLAG_USESEEKRESULT); */
  sqlite4VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
  sqlite4VdbeChangeP5(v, SQLITE4_STMTSTATUS_AUTOINDEX);
  sqlite4VdbeJumpHere(v, addrTop);
  sqlite4ReleaseTempRange(pParse, regRecord, 2);
  
  /* Jump here when skipping the initialization */