/ Check-in [c1adf959]
Login

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

Overview
Comment:Add an optimization to OP_Column to speed up sequential OP_Column instructions that read earlier fields from the same cursor. Attempt to reorder OP_Column opcodes so as to take advantage of this.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | sort-column-opcodes
Files: files | file ages | folders
SHA1: c1adf95958d5210bf9f89fc86d0f6fc6ce32c480
User & Date: dan 2017-02-18 20:05:05
Context
2017-02-18
20:05
Add an optimization to OP_Column to speed up sequential OP_Column instructions that read earlier fields from the same cursor. Attempt to reorder OP_Column opcodes so as to take advantage of this. Leaf check-in: c1adf959 user: dan tags: sort-column-opcodes
13:47
Add the SQLITE_BUG_COMPATIBLE_20160819 compile-time option to omit the error message when an unrecognized argument is provided to the VACUUM command. check-in: 49181427 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/expr.c.

4147
4148
4149
4150
4151
4152
4153


































































































4154
4155
4156
4157
4158
4159
4160
....
4173
4174
4175
4176
4177
4178
4179

4180
4181
4182
4183
4184
4185
4186
4187
4188








4189
4190
4191
4192
4193
4194
4195
....
4207
4208
4209
4210
4211
4212
4213

4214
4215
4216
4217
4218
4219
4220
  assert( target>0 );
  assert( pExpr->op!=TK_REGISTER );
  sqlite3ExprCode(pParse, pExpr, target);
  iMem = ++pParse->nMem;
  sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
  exprToRegister(pExpr, iMem);
}



































































































/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
** Return the number of elements evaluated.
**
................................................................................
  ExprList *pList,   /* The expression list to be coded */
  int target,        /* Where to write results */
  int srcReg,        /* Source registers if SQLITE_ECEL_REF */
  u8 flags           /* SQLITE_ECEL_* flags */
){
  struct ExprList_item *pItem;
  int i, j, n;

  u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
  Vdbe *v = pParse->pVdbe;
  assert( pList!=0 );
  assert( target>0 );
  assert( pParse->pVdbe!=0 );  /* Never gets this far otherwise */
  n = pList->nExpr;
  if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
  for(pItem=pList->a, i=0; i<n; i++, pItem++){
    Expr *pExpr = pItem->pExpr;








    if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){
      if( flags & SQLITE_ECEL_OMITREF ){
        i--;
        n--;
      }else{
        sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
      }
................................................................................
          pOp->p3++;
        }else{
          sqlite3VdbeAddOp2(v, copyOp, inReg, target+i);
        }
      }
    }
  }

  return n;
}

/*
** Generate code for a BETWEEN operator.
**
**    x BETWEEN y AND z







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>









>
>
>
>
>
>
>
>







 







>







4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
....
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
....
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
  assert( target>0 );
  assert( pExpr->op!=TK_REGISTER );
  sqlite3ExprCode(pParse, pExpr, target);
  iMem = ++pParse->nMem;
  sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
  exprToRegister(pExpr, iMem);
}

/*
** Return the value of (*p1) - (*p2), as defined by the sort order described
** in the comment above reorderColumnFetch(). 
*/
static int compareOpCode(VdbeOp *p1, VdbeOp *p2){
  int res;

  assert( p1->opcode==OP_Column || p1->opcode==OP_VColumn
       || p1->opcode==OP_Copy   || p1->opcode==OP_SCopy
       || p1->opcode==OP_Rowid  || p1->opcode==OP_RealAffinity
  );
  assert( p2->opcode==OP_Column || p2->opcode==OP_VColumn
       || p2->opcode==OP_Copy   || p2->opcode==OP_SCopy
       || p2->opcode==OP_Rowid  || p2->opcode==OP_RealAffinity
  );

  assert( OP_VColumn>OP_Column && OP_Rowid>OP_Column );
  assert( OP_Column>OP_RealAffinity );
  assert( OP_RealAffinity>OP_Copy && OP_RealAffinity>OP_SCopy );

  res = (int)(p2->opcode) - (int)(p1->opcode);
  if( res==0 ){
    res = p1->p1 - p2->p1;
    if( res==0 ){
      res = p2->p2 - p1->p2;
    }
  }
  return res;
}

/*
** The VM instructions from iFirst to the current address were generated
** in order to populate an array of registers with the results of a series
** of TK_COLUMN expressions. This guarantees that the specified range 
** contains opcodes of the following types only:
**
**   Rowid
**   Column
**   VColumn
**   RealAffinity
**   Copy
**   SCopy
**
** This function sorts the opcodes so all of the OP_Column appear in a
** contiguous block, sorted by (p1, p2 DESC). The VDBE layer processes
** OP_Column instructions in this order more efficiently.
**
** In practice, the array is sorted so that all instructions of each type 
** of opcode are arranged into a contiguous group. Given the following,
** this is a safe re-ordering:
**
**   * All Rowid, VColumn and Column instructions appear before all 
**     RealAffinity instructions (that might operate on the result of
**     a VColumn or Column), and
**
**   * All RealAffinity instructions occur before all Copy and SCopy
**     instructions (which might read a column-cache entry populated
**     by a prior Column+RealAffinity).
*/
static void reorderColumnFetch(sqlite3 *db, Vdbe *v, int iFirst){
  int iEnd = sqlite3VdbeCurrentAddr(v);
  int nOp = iEnd-iFirst;
  if( nOp>1 ){
    VdbeOp *aSpace = (VdbeOp*)sqlite3StackAllocRaw(db, sizeof(VdbeOp) * nOp);
    if( aSpace ){
      int sz;
      VdbeOp *aOp = sqlite3VdbeGetOp(v, iFirst);
      VdbeOp *a1 = aOp;
      VdbeOp *a2 = aSpace;
      for(sz=1; sz<nOp; sz=sz*2){
        int i;
        for(i=0; i<nOp; i+=(sz*2)){
          /* Merge the two lists of sz elements each starting at a1[i] and 
          ** a1[i+sz] into a sz element list at a2[i].  */
          int e1 = MIN(i+sz, nOp);
          int e2 = MIN(i+sz*2, nOp);
          int i2 = i+sz;
          int i1 = i;
          int iOut = i;

          while( i1<e1 || i2<e2 ){
            if( i1>=e1 || (i2<e2 && compareOpCode(&a1[i2], &a1[i1])<0) ){
              a2[iOut++] = a1[i2++];
            }else{
              a2[iOut++] = a1[i1++];
            }
          }
        }
        SWAP(VdbeOp*, a1, a2);
      }
      if( a1!=aOp ){
        memcpy(aOp, a1, sizeof(VdbeOp)*nOp);
      }
      sqlite3StackFree(db, aSpace);
    }
  }
}

/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
** Return the number of elements evaluated.
**
................................................................................
  ExprList *pList,   /* The expression list to be coded */
  int target,        /* Where to write results */
  int srcReg,        /* Source registers if SQLITE_ECEL_REF */
  u8 flags           /* SQLITE_ECEL_* flags */
){
  struct ExprList_item *pItem;
  int i, j, n;
  int iFirst = -1;
  u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
  Vdbe *v = pParse->pVdbe;
  assert( pList!=0 );
  assert( target>0 );
  assert( pParse->pVdbe!=0 );  /* Never gets this far otherwise */
  n = pList->nExpr;
  if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
  for(pItem=pList->a, i=0; i<n; i++, pItem++){
    Expr *pExpr = pItem->pExpr;
    if( iFirst>0 ){
      if( pExpr->op!=TK_COLUMN ){
        reorderColumnFetch(pParse->db, v, iFirst);
        iFirst = -1;
      }
    }else{
      if( pExpr->op==TK_COLUMN ) iFirst = sqlite3VdbeCurrentAddr(v);
    }
    if( (flags & SQLITE_ECEL_REF)!=0 && (j = pItem->u.x.iOrderByCol)>0 ){
      if( flags & SQLITE_ECEL_OMITREF ){
        i--;
        n--;
      }else{
        sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i);
      }
................................................................................
          pOp->p3++;
        }else{
          sqlite3VdbeAddOp2(v, copyOp, inReg, target+i);
        }
      }
    }
  }
  if( iFirst>0 ) reorderColumnFetch(pParse->db, v, iFirst);
  return n;
}

/*
** Generate code for a BETWEEN operator.
**
**    x BETWEEN y AND z

Changes to src/select.c.

1270
1271
1272
1273
1274
1275
1276

1277
1278
1279


1280
1281
1282


1283




1284
1285
1286

1287
1288
1289
1290
1291
1292
1293
    bSeq = 0;
  }else{
    addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
    codeOffset(v, p->iOffset, addrContinue);
    iSortTab = iTab;
    bSeq = 1;
  }

  for(i=0, iCol=nKey+bSeq; i<nSortData; i++){
    int iRead;
    if( aOutEx[i].u.x.iOrderByCol ){


      iRead = aOutEx[i].u.x.iOrderByCol-1;
    }else{
      iRead = iCol++;


    }




    sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
    VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
  }

  switch( eDest ){
    case SRT_Table:
    case SRT_EphemTab: {
      sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
      sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
      sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
      break;







>
|
<
|
>
>
|
<
<
>
>

>
>
>
>



>







1270
1271
1272
1273
1274
1275
1276
1277
1278

1279
1280
1281
1282


1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
    bSeq = 0;
  }else{
    addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
    codeOffset(v, p->iOffset, addrContinue);
    iSortTab = iTab;
    bSeq = 1;
  }
  iCol = nKey+bSeq;
  for(i=0; i<nSortData; i++){

    if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++;
  }
  for(i=nSortData-1; i>=0; i--){
    if( aOutEx[i].u.x.iOrderByCol==0 ){


      sqlite3VdbeAddOp3(v, OP_Column, iSortTab, --iCol, regRow+i);
      VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName:aOutEx[i].zSpan));
    }
  }
  for(i=nSortData-1; i>=0; i--){
    if( aOutEx[i].u.x.iOrderByCol ){
      int iRead = aOutEx[i].u.x.iOrderByCol-1;
      sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
      VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName:aOutEx[i].zSpan));
    }
  }
  switch( eDest ){
    case SRT_Table:
    case SRT_EphemTab: {
      sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
      sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
      sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
      break;

Changes to src/sqliteInt.h.

3076
3077
3078
3079
3080
3081
3082


3083
3084
3085
3086
3087
3088
3089
#define OPFLAG_BULKCSR       0x01    /* OP_Open** used to open bulk cursor */
#define OPFLAG_SEEKEQ        0x02    /* OP_Open** cursor uses EQ seek only */
#define OPFLAG_FORDELETE     0x08    /* OP_Open should use BTREE_FORDELETE */
#define OPFLAG_P2ISREG       0x10    /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE       0x01    /* OP_Compare: use the permutation */
#define OPFLAG_SAVEPOSITION  0x02    /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE     0x04    /* OP_Delete: index in a DELETE op */



/*
 * Each trigger present in the database schema is stored as an instance of
 * struct Trigger.
 *
 * Pointers to instances of struct Trigger are stored in two ways.
 * 1. In the "trigHash" hash table (part of the sqlite3* that represents the







>
>







3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
#define OPFLAG_BULKCSR       0x01    /* OP_Open** used to open bulk cursor */
#define OPFLAG_SEEKEQ        0x02    /* OP_Open** cursor uses EQ seek only */
#define OPFLAG_FORDELETE     0x08    /* OP_Open should use BTREE_FORDELETE */
#define OPFLAG_P2ISREG       0x10    /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE       0x01    /* OP_Compare: use the permutation */
#define OPFLAG_SAVEPOSITION  0x02    /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE     0x04    /* OP_Delete: index in a DELETE op */

#define OPFLAG_CONTINUE      0x01

/*
 * Each trigger present in the database schema is stored as an instance of
 * struct Trigger.
 *
 * Pointers to instances of struct Trigger are stored in two ways.
 * 1. In the "trigHash" hash table (part of the sqlite3* that represents the

Changes to src/update.c.

543
544
545
546
547
548
549



550

551
552
553
554
555
556
557
  ** the database after the BEFORE triggers are fired anyway (as the trigger 
  ** may have modified them). So not loading those that are not going to
  ** be used eliminates some redundant opcodes.
  */
  newmask = sqlite3TriggerColmask(
      pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
  );



  for(i=0; i<pTab->nCol; i++){

    if( i==pTab->iPKey ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
    }else{
      j = aXRef[i];
      if( j>=0 ){
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){







>
>
>

>







543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
  ** the database after the BEFORE triggers are fired anyway (as the trigger 
  ** may have modified them). So not loading those that are not going to
  ** be used eliminates some redundant opcodes.
  */
  newmask = sqlite3TriggerColmask(
      pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
  );
#if 1
  for(i=pTab->nCol-1; i>=0; i--){
#else
  for(i=0; i<pTab->nCol; i++){
#endif
    if( i==pTab->iPKey ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
    }else{
      j = aXRef[i];
      if( j>=0 ){
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
      }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){

Changes to src/vdbe.c.

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
....
2623
2624
2625
2626
2627
2628
2629

2630
2631
2632
2633
2634
2635
2636

2637
2638
2639
2640
2641
2642
2643
....
2645
2646
2647
2648
2649
2650
2651













2652
2653
2654
2655
2656
2657
2658
    return out2PrereleaseWithClear(pOut);
  }else{
    pOut->flags = MEM_Int;
    return pOut;
  }
}


/*
** Execute as much of a VDBE program as we can.
** This is the core of sqlite3_step().  
*/
int sqlite3VdbeExec(
  Vdbe *p                    /* The VDBE */
){
................................................................................
  if( VdbeMemDynamic(pDest) ){
    sqlite3VdbeMemSetNull(pDest);
  }
  assert( t==pC->aType[p2] );
  if( pC->szRow>=aOffset[p2+1] ){
    /* This is the common case where the desired content fits on the original
    ** page - where the content is not on an overflow page */

    zData = pC->aRow + aOffset[p2];
    if( t<12 ){
      sqlite3VdbeSerialGet(zData, t, pDest);
    }else{
      /* If the column value is a string, we need a persistent value, not
      ** a MEM_Ephem value.  This branch is a fast short-cut that is equivalent
      ** to calling sqlite3VdbeSerialGet() and sqlite3VdbeDeephemeralize().

      */
      static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
      pDest->n = len = (t-12)/2;
      pDest->enc = encoding;
      if( pDest->szMalloc < len+2 ){
        pDest->flags = MEM_Null;
        if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
................................................................................
        pDest->z = pDest->zMalloc;
      }
      memcpy(pDest->z, zData, len);
      pDest->z[len] = 0;
      pDest->z[len+1] = 0;
      pDest->flags = aFlag[t&1];
    }













  }else{
    pDest->enc = encoding;
    /* This branch happens only when content is on overflow pages */
    if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
          && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
     || (len = sqlite3VdbeSerialTypeLen(t))==0
    ){







<







 







>





|
|
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>







549
550
551
552
553
554
555

556
557
558
559
560
561
562
....
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
....
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
    return out2PrereleaseWithClear(pOut);
  }else{
    pOut->flags = MEM_Int;
    return pOut;
  }
}


/*
** Execute as much of a VDBE program as we can.
** This is the core of sqlite3_step().  
*/
int sqlite3VdbeExec(
  Vdbe *p                    /* The VDBE */
){
................................................................................
  if( VdbeMemDynamic(pDest) ){
    sqlite3VdbeMemSetNull(pDest);
  }
  assert( t==pC->aType[p2] );
  if( pC->szRow>=aOffset[p2+1] ){
    /* This is the common case where the desired content fits on the original
    ** page - where the content is not on an overflow page */
    while( 1 ){
      zData = pC->aRow + aOffset[p2];
      if( t<12 ){
        sqlite3VdbeSerialGet(zData, t, pDest);
      }else{
        /* If the column value is a string, we need a persistent value, not
        ** a MEM_Ephem value.  This branch is a fast short-cut that is
        ** equivalent to calling sqlite3VdbeSerialGet() and
        ** sqlite3VdbeDeephemeralize().
        */
        static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
        pDest->n = len = (t-12)/2;
        pDest->enc = encoding;
        if( pDest->szMalloc < len+2 ){
          pDest->flags = MEM_Null;
          if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
................................................................................
          pDest->z = pDest->zMalloc;
        }
        memcpy(pDest->z, zData, len);
        pDest->z[len] = 0;
        pDest->z[len+1] = 0;
        pDest->flags = aFlag[t&1];
      }

      if( (pOp->p5 & OPFLAG_CONTINUE)==0 ) break;
      UPDATE_MAX_BLOBSIZE(pDest);
      REGISTER_TRACE(pOp->p3, pDest);
      pOp++;
      p2 = pOp->p2;
      t = pC->aType[p2];
      pDest = &aMem[pOp->p3];
      memAboutToChange(p, pDest);
      if( VdbeMemDynamic(pDest) ){
        sqlite3VdbeMemSetNull(pDest);
      }
    }
  }else{
    pDest->enc = encoding;
    /* This branch happens only when content is on overflow pages */
    if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
          && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
     || (len = sqlite3VdbeSerialTypeLen(t))==0
    ){

Changes to src/vdbe.h.

222
223
224
225
226
227
228

229
230
231
232
233
234
235
void sqlite3VdbeCountChanges(Vdbe*);
sqlite3 *sqlite3VdbeDb(Vdbe*);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
void sqlite3VdbeSetVarmask(Vdbe*, int);

#ifndef SQLITE_OMIT_TRACE
  char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);

void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);







>







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
void sqlite3VdbeCountChanges(Vdbe*);
sqlite3 *sqlite3VdbeDb(Vdbe*);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
void sqlite3VdbeSetVarmask(Vdbe*, int);
void sqlite3VdbeUsesAltMap(Vdbe*);
#ifndef SQLITE_OMIT_TRACE
  char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);

void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);

Changes to src/vdbeInt.h.

386
387
388
389
390
391
392

393
394
395
396
397
398
399
  bft explain:2;          /* True if EXPLAIN present on SQL command */
  bft changeCntOn:1;      /* True to update the change-counter */
  bft runOnlyOnce:1;      /* Automatically expire on reset */
  bft usesStmtJournal:1;  /* True if uses a statement journal */
  bft readOnly:1;         /* True for statements that do not write */
  bft bIsReader:1;        /* True for statements that read */
  bft isPrepareV2:1;      /* True if prepared with prepare_v2() */

  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
  yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
  u32 aCounter[5];        /* Counters used by sqlite3_stmt_status() */
  char *zSql;             /* Text of the SQL statement that generated this */
  void *pFree;            /* Free this when deleting the vdbe */
  VdbeFrame *pFrame;      /* Parent frame */
  VdbeFrame *pDelFrame;   /* List of frame objects to free on VM reset */







>







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
  bft explain:2;          /* True if EXPLAIN present on SQL command */
  bft changeCntOn:1;      /* True to update the change-counter */
  bft runOnlyOnce:1;      /* Automatically expire on reset */
  bft usesStmtJournal:1;  /* True if uses a statement journal */
  bft readOnly:1;         /* True for statements that do not write */
  bft bIsReader:1;        /* True for statements that read */
  bft isPrepareV2:1;      /* True if prepared with prepare_v2() */
  bft usesAltMap:1;       /* True if uses VdbeCursor.aAltMap[] */
  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
  yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
  u32 aCounter[5];        /* Counters used by sqlite3_stmt_status() */
  char *zSql;             /* Text of the SQL statement that generated this */
  void *pFree;            /* Free this when deleting the vdbe */
  VdbeFrame *pFrame;      /* Parent frame */
  VdbeFrame *pDelFrame;   /* List of frame objects to free on VM reset */

Changes to src/vdbeaux.c.

614
615
616
617
618
619
620







621
622
623
624
625
626
627
....
4553
4554
4555
4556
4557
4558
4559






4560
4561
4562
4563
4564
4565
4566
      if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 && pOp->p2<0 ){
        assert( ADDR(pOp->p2)<pParse->nLabel );
        pOp->p2 = aLabel[ADDR(pOp->p2)];
      }
    }
    if( pOp==p->aOp ) break;
    pOp--;







  }
  sqlite3DbFree(p->db, pParse->aLabel);
  pParse->aLabel = 0;
  pParse->nLabel = 0;
  *pMaxFuncArgs = nMaxArgs;
  assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
}
................................................................................
  if( iVar>32 ){
    v->expmask = 0xffffffff;
  }else{
    v->expmask |= ((u32)1 << (iVar-1));
  }
}







#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/
void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){







>
>
>
>
>
>
>







 







>
>
>
>
>
>







614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
....
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
      if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 && pOp->p2<0 ){
        assert( ADDR(pOp->p2)<pParse->nLabel );
        pOp->p2 = aLabel[ADDR(pOp->p2)];
      }
    }
    if( pOp==p->aOp ) break;
    pOp--;

    if( p->usesAltMap==0 
     && pOp[0].opcode==OP_Column && pOp[1].opcode==OP_Column
     && pOp[0].p1==pOp[1].p1 && pOp[0].p2>=pOp[1].p2
    ){
      pOp->p5 |= OPFLAG_CONTINUE;
    }
  }
  sqlite3DbFree(p->db, pParse->aLabel);
  pParse->aLabel = 0;
  pParse->nLabel = 0;
  *pMaxFuncArgs = nMaxArgs;
  assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
}
................................................................................
  if( iVar>32 ){
    v->expmask = 0xffffffff;
  }else{
    v->expmask |= ((u32)1 << (iVar-1));
  }
}

/*
** Set the "uses-alt-map" flag.
*/
void sqlite3VdbeUsesAltMap(Vdbe *v){
  v->usesAltMap = 1;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/
void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){

Changes to src/wherecode.c.

999
1000
1001
1002
1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
      ai[0] = pTab->nCol;
      for(i=0; i<pIdx->nColumn-1; i++){
        assert( pIdx->aiColumn[i]<pTab->nCol );
        if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1;
      }
      sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
    }

  }
}

/*
** If the expression passed as the second argument is a vector, generate
** code to write the first nReg elements of the vector into an array
** of registers starting with iReg.







>







999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
      ai[0] = pTab->nCol;
      for(i=0; i<pIdx->nColumn-1; i++){
        assert( pIdx->aiColumn[i]<pTab->nCol );
        if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1;
      }
      sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
    }
    sqlite3VdbeUsesAltMap(v);
  }
}

/*
** If the expression passed as the second argument is a vector, generate
** code to write the first nReg elements of the vector into an array
** of registers starting with iReg.